\input utexinfo   @c -*- Texinfo -*-
@comment %**start of header (This is for running Texinfo on a region.)
@setfilename netcdf
@settitle netCDF User's Guide
@setchapternewpage odd
@comment %**end of header (This is for running Texinfo on a region.)

@iftex
@finalout
@end iftex

@comment Combine the variable and function indices.
@synindex vr fn

@ifinfo
This file documents the Unidata netCDF interface, library, and
utilities.  Copyright (C) 1988, 1989, 1990 University Corporation for
Atmospheric Research.

Permission is granted to make and distribute verbatim copies of
this file provided the copyright notice and this permission notice
are preserved on all copies.
@end ifinfo

@titlepage
@sp 6
@center @titlefont{netCDF User's Guide}
@sp 2
@center An Interface for Data Access
@sp 2
@center Version 1.06, June 1990
@sp 2
@center by Russell K. Rew, Unidata Program Center
@page
@vskip 0pt plus 1filll
@center Copyright @copyright{} 1988, 1989, 1990 by UCAR
@sp 2
@center University Corporation for Atmospheric Research
@sp 2
@center All Rights Reserved
@sp 2
Permission is granted to make and distribute verbatim copies of this 
manual provided that the copyright notice and these paragraphs are 
preserved on all copies.  The software and any accompanying written 
materials are provided ``as is'' without warranty of any kind.  UCAR 
expressly disclaims all warranties of any kind, either expressed or 
implied, including but not limited to the implied warranties of 
merchantability and fitness for a particular purpose.  

The Unidata Program Center is managed by the University 
Corporation for Atmospheric Research and sponsored by the National 
Science Foundation.  Any opinions, findings, conclusions, or 
recommendations expressed in this publication are those of the 
author(s) and do not necessarily reflect the views of the National 
Science Foundation.

Mention of any commercial company or product in this document 
does not constitute an endorsement by the Unidata Program Center.  
Unidata does not authorize any use of information from this 
publication for advertising or publicity purposes.
@end titlepage
@page

@node     Top, Foreward, (dir), (dir)
@comment  node-name,  next,  previous,  up

@ifinfo
The Unidata netCDF library provides an application- and
machine-independent interface to self-describing, multidimensional
scientific data.  It supports an abstract view of scientific data as a
collection of named variables and their attributes, and provides
high-level access to data that is faithful to the abstraction.  This
on-line document describes the netCDF abstraction, applications programming
interfaces, and utilities.  It includes the following chapters:
@end ifinfo

@menu
* Foreward::     What is Unidata?
* Summary::      Brief purpose and description of netCDF.
* Introduction:: Overview and background of netCDF.
* Components::   The components of a netCDF file.
* Data::         The primitive netCDF data types and forms of data
                  access.
* Usage::        How to use the netCDF library.
* File Operations::The interface for handling netCDF files.
* Dimensions::	 The interface for handling netCDF dimensions.
* Variables::	 The interface for handling netCDF variables.
* Attributes::	 The interface for handling netCDF attributes.
* Miscellaneous::The interface for miscellaneous netCDF operations.
* Utilities::    Higher-level netCDF operations implemented as separate
                  programs.
* Getting the Software::How to obtain netCDF software.
* C Interface::  A summary of the C interface.
* Fortran Interface::A summary of the Fortran interface.
* Name Index::  Index of cross-references for names of netCDF functions and
                 variables.
* General Index::Index of concepts.
@end menu


@unnumbered Acknowledgments
For helping to make this first release of the Unidata netCDF software
possible, we would like to acknowledge the efforts of
@itemize @bullet
@item
Joe Fahle, SeaSpace, Inc.
@item
Michael Gough, Apple Computer
@item
Angel Li, University of Miami
@item
Dave Raymond, New Mexico Institute of Mining and Technology
@item
Lloyd Treinish, NASA/NSSDC
@end itemize

@node Foreward, Summary, Top, Top
@unnumbered Foreword

Unidata is a national effort, sponsored by the Division of Atmospheric
Sciences of the National Science Foundation (NSF), to help universities
use computing and communication technologies to access, analyze, and
display atmospheric and related data.  The program, which is managed by
the University Corporation for Atmospheric Research, was begun in 1982
in response to (1) university interests in wider application of
interactive processing and display methods to atmospheric science
research and education and (2) university concerns about the future
availability of and costs for National Weather Service (NWS) data (the
distribution modes were being altered by the Automation of Field
Operations and Services [AFOS] program).  Unidata now provides
universities with inexpensive access to near-real-time weather data
accompanied with capabilities to select, organize, analyze, and display
those data interactively.

The Unidata system represents the results of a partnership between the
universities and the Unidata Program Center in Boulder, Colorado.  The
goal of the program office is to provide a system to the universities,
with the capabilities described above, based upon modern communications
technology and personal workstations.  Universities participate in
establishing Unidata policies, specifying broadcast services, developing
software, and they provide technical assistance to one another.  The
program center's role is to coordinate community efforts nationwide, to
provide software, and to help universities select and use networked
computing systems.

Most Unidata sites are connected to NSFnet, NSF's scientific research
network.  Such connections provide convenient access to the Program
Center for obtaining current copies of software, documentation,
announcements, and software updates as well as for reporting problems
and requesting assistance.

Unidata distributes a number of software packages.  One is an image
display and data-handling system developed by the Space Science and
Engineering Center (SSEC) of the University of Wisconsin--Madison.  This
software, called PC-McIDAS (for Man--Computer Interactive Data Access
System) runs on IBM PS/2 computers using the OS/2 operating system.

In addition, Unidata is distributing a composite package of data
handling, analysis and display software for VMS- and UNIX-based systems,
which includes community contributions from several sources.  Unidata's
goal is to standardize the user interface, the data-access interface,
and the display interface, and to adapt existing applications software
to match these three.  Beyond the suite of capabilities thus provided,
the approach maximizes the programmability of the system: users may add
new applications at will so long as the interface standards are
observed.  This composite package is known as Unidata's Scientific Data
Management (SDM) system.

The Network Common Data Form (netCDF) software package described in this
manual was developed initially as part of the SDM system and is
distributed with it.  In essence, the netCDF is the ``standard''
data-access interface employed by the various SDM software components.
The netCDF software, however, may be useful in a wider context.  In
recognition of this, Unidata provides the software and its documentation
separately.

@noindent
David Fulker, Director@*
Unidata Program Center

@node Summary, Introduction, Foreward, Top
@unnumbered Summary
@cindex self-describing
@cindex network-transparent
The purpose of the Network Common Data Form (netCDF) interface is to
allow you to create, access, and share scientific data in a form that is
self-describing and network-transparent.  ``Self-describing'' means that a
file includes information defining the data it contains.
``Network-transparent'' means that a file is represented in a form that
can be accessed by computers with different ways of storing integers,
characters, and floating-point numbers.  Using the netCDF interface for
creating new scientific data sets can improve the accessibility of the
data.  Using the netCDF interface in new software for scientific data
access, management, analysis, and display can improve the reusability of
the software for other data sets and by other users.

@cindex FORTRAN interface
The netCDF software provides common C and FORTRAN interfaces for
applications and data.  The C interface library is available for many
common computing platforms, including UNIX, VMS, MSDOS, and MacOS
environments.  The FORTRAN interface is currently available for a
smaller set of environments (due to the lack of a standard for calling C
from FORTRAN).

The netCDF software is being made freely available to encourage the
sharing of both scientific data and the software that makes the data
useful.

@node Introduction, Components, Summary, Top
@chapter Introduction
@section The netCDF Interface

@cindex netCDF
The Network Common Data Form, or netCDF, is an interface to a library of
data access programs for storing and retrieving scientific data.  The
netCDF is an abstraction that supports a view of data as a collection of
self-describing, network-transparent objects that can be accessed
through a simple interface.  Collections of named multidimensional
variables can be randomly accessed, without knowing details of how the
data are stored.  Auxiliary information about the data, such as what
units are used, can be stored with the data.  Generic utilities and
application programs can be written that access arbitrary netCDF files
and transform, combine, analyze, or display specified fields of the
data.  The development of such applications may lead to improved
accessibility of data and improved reusability of software for
scientific data management, analysis, and display.

@cindex availability of netCDF software
@cindex languages supported
@cindex operating systems supported
@cindex portability

The netCDF software that implements this interface is being made freely
available to encourage its wide use.  The netCDF interface is supported
for both C and FORTRAN, and can be used with UNIX, VMS, MSDOS, and MacOS
operating systems.  Porting the software to other operating systems
should not be difficult.

@cindex abstract data type
@cindex future changes planned

The netCDF software implements an @dfn{abstract data type}, which means
that all operations to access and manipulate data in a netCDF file must use
only the set of functions provided by the interface.  The actual
representation of the data is hidden from applications that use the
interface, so that how the data are stored could be changed without
affecting such programs.  The physical representation of netCDF data is
designed to be independent of the computer on which the data were
written.  Future changes to the netCDF interface will be compatible with
the interface described here, so that neither existing netCDF files nor
programs accessing them will require modification.

@menu
* Not a DBMS::   NetCDF is not a database management system.
* Performance::  Some performance considerations.
* Archiving::    Is netCDF a good archive format?
* History::      Background and Evolution of the netCDF Interface.
* Future Plans:: Future plans for netCDF.
@end menu

@node Not a DBMS, Performance, , Introduction
@section The netCDF is Not a Database Management System

@cindex database management systems
Why not use an existing database management system (DBMS)
for storing scientific data?  We have looked at available database
packages, both commercial and research-oriented, and have concluded that
they are currently inadequate for achieving the goals of the netCDF.

@cindex relational database systems

First, most existing DBMSs have poor support for multidimensional
objects as the basic unit of data access.  Related to this is a second
problem with general-purpose database systems:  their poor performance
on large scientific data sets.  Collections of satellite images,
scientific model outputs, climate observations covering decades,
high-resolution atmospheric profile data, and other large data sets
are beyond the capabilities of most DBMSs to organize and index for
efficient retrieval.

Another problem is that DBMSs provide many facilities that are not
needed in the analysis, management, and display of scientific data.
Elaborate update facilities, concurrency control, audit trails, report
writers, and other mechanisms designed for transaction-processing are
unnecessary for the applications served by the netCDF interface.  The
resources and expense required to support these unnecessary facilities
cannot be justified for scientific applications.

Other requirements that are difficult to satisfy with existing database
systems include support for both C and FORTRAN procedural interfaces,
ability to run on both UNIX and VMS systems, and support for an
architecture-independent format for representing scientific data.

@node Performance, Archiving, Not a DBMS, Introduction
@section What about Performance?

@cindex efficiency
@cindex performance
@cindex external data representation (XDR)
@cindex XDR
To achieve network-transparency, the netCDF is implemented on top of a
layer of software for external data representation (XDR).  XDR,
developed by Sun Microsystems, Inc., is a nonproprietary standard for
describing and encoding data.  It supports encoding arbitrary C
data structures into machine-independent sequences of bits.
@cindex IEEE floating-point
The encoding used for floating-point numbers is the Institute for
Electrical and Electronics Engineers (IEEE) standard for normalized
floating-point numbers.  XDR has been implemented on a wide variety of
computers, including SUNs, VAXs, Apple Macintoshes, IBM-PCs, IBM
mainframes, and CRAYs.  It assumes only that 8-bit bytes can be encoded
and decoded in a consistent way.

Translating data into and out of XDR form adds overhead to data
transfers, but for many applications the extra CPU cycles used to
convert data to and from a machine-independent representation are not
significant.  We are currently considering whether a native mode that
does not use XDR would be a useful addition to the netCDF
implementation.  The amount of XDR overhead depends on many factors,
including the data type, the type of computer, the granularity of data
access, and how well the implementation has been tuned to the computer
on which it is run.  For many applications, we consider the overhead of
the XDR layer to be a reasonable price to pay for portable,
network-transparent data access.

@cindex performance
@cindex efficiency
Often when an abstraction layer is added to hide the details of an
underlying implementation from applications, it becomes possible to
express simply computations that may require large amounts of computing
resources.  Furthermore, it may not be obvious which of several ways of
expressing a computation through the new interface will make efficient
use of computing resources, without understanding something about the
implementation.  It is certainly possible to use the netCDF interface to
access data in inefficient ways: for example, if the user makes a
request for a slice of variable data that requires a single value out of
each record.  This manual discusses characteristics of the netCDF
implementation at those points where it is important to know something
about how the underlying software works to use the interface
effectively.

@node Archiving, History, Performance, Introduction
@section Is netCDF a Good Archive Format?

@cindex archive formats
The netCDF can be used as an archive format for storing data, but it
will generally take more space than a special-purpose archive format
that exploits knowledge of particular characteristics of a set of data.
While compression is possible for low-resolution data by using, for
example, eight-bit bytes instead of 32-bit floating-point numbers, the
netCDF was not designed to achieve optimal compression of scientific
data.

The advantages of a special-purpose archive format for small archives
should be compared to the benefits of machine-independence and the
ability to store metadata (data about the data) that the netCDF
interface provides.  For large archives, only two programs need to be
provided for each archive format, one to translate archived data into
netCDF form and the other to translate back to the archive format.
Tools provided for manipulating netCDF data will then be available
without sacrificing the advantages of the archive format and without
requiring the wholesale conversion of large existing archives.

@node History, Future Plans, Archiving, Introduction
@section Background and Evolution of the netCDF Interface

@cindex history of the netCDF
@cindex netCDF, development of
The development of the netCDF began with a modest goal related to
Unidata's needs: to provide a common interface between Unidata
applications and ingested real-time meteorological data.  Since Unidata
software was intended to run on both Suns and MicroVAXs, with access
from both C and FORTRAN software, achieving Unidata's goals had the
potential for providing a package that was useful in a broader context.
By making the package widely available and collaborating with other
organizations with similar needs, we hoped to improve the current
situation in which scientific software is only rarely reused by others
in the same discipline and almost never reused between disciplines
(Fulker, 1988).

@cindex NASA CDF
@cindex NSSDC CDF
Important concepts employed in the netCDF originated in a paper (Treinish
and Gough, 1987) that described software developed at the NASA
Goddard National Space Science Data Center (NSSDC).  The interface
provided by this software was called the Common Data Format (CDF).  The
NASA CDF was developed as a FORTRAN library for VAX/VMS systems to
support an abstraction for storing multidimensional scientific data.

The NASA CDF package has been used for many different kinds
of data in an extensive collection of applications.  It
has the virtues of simplicity (only 13 subroutines), independence from
storage format, generality, ability to support logical user views of
data, and support for generic applications.

@cindex Unidata CDF Workshops
Unidata held a workshop on CDF in Boulder in August 1987.  Its purposes
were to explore the possibility of collaborating with NASA to extend the
CDF to work with FORTRAN compilers not employing VMS extensions; to
define a C interface; and to permit the access of data aggregates with a
single call, while maintaining compatibility with the existing NASA
interface.

@cindex New Mexico Tech. CDF
@cindex CANDIS
Independently, Dave Raymond at the New Mexico Institute of Mining and
Technology had developed a package of C software for UNIX that supported
self-describing scientific data along with a ``pipes and filters''
approach to processing, analyzing, and displaying scientific data.
Coincidentally, this package also used the common data format name,
which was later changed to C-Based Analysis and Display System (CANDIS).
Unidata learned of Raymond's work, described in (Raymond, 1988), and
incorporated some of his ideas, such as the use of named dimensions and
variables with differing shapes in a single data object, into the
Unidata netCDF.

@cindex XDR
In early 1988, Glenn Davis of Unidata developed a prototype netCDF
package in C that was layered on a nonproprietary external data
representation standard (XDR) developed by Sun Microsystems.  This
prototype proved that a single-file, network-transparent implementation
of the CDF interface could be achieved at acceptable cost and that the
resulting programs could be implemented on both UNIX and VMS systems.
However, it also demonstrated that providing a small, portable, and NASA
CDF-compatible FORTRAN interface with the desired generality was not
practical.

@cindex SeaSpace CDF
In early 1988, Joe Fahle of SeaSpace, Inc. (a commercial software
development firm in San Diego, California), a participant in the 1987
Unidata CDF workshop, independently developed a CDF package in C that
extended the NASA CDF in several important ways (Fahle, 1989).  Like Raymond's
package, the SeaSpace CDF permitted variables with unrelated shapes to
be included in the same data object and permitted a general
``hyperslab'' form of access to multidimensional arrays.  Fahle's
implementation was used at SeaSpace as the intermediate form of storage
for a variety of steps in their image-processing system.

@cindex Unidata CDF Workshops
After studying Fahle's interface, we concluded that it solved many of
the problems we had identified in trying to stretch the NASA interface
to our purposes.  In August 1988, we convened a small workshop to agree
on a Unidata netCDF interface, and to resolve remaining open issues.
Attending were Joe Fahle of SeaSpace, Michael Gough of Apple (an author
of the NASA CDF), Angel Li of the University of Miami (who had
implemented our prototype netCDF on VMS and was a potential user), and
Unidata systems development staff.  Consensus was reached at the
workshop after some further simplifications were discovered.  A document
incorporating the results of the workshop into a proposed Unidata netCDF
interface specification was distributed widely for comments before
implementing the software it described.  Comparison with alternatives
and recent experience in using netCDF are discussed in a
conference preprint volume (Rew and Davis, 1990).

@node Future Plans, References, History, Introduction
@section Future Plans for netCDF

@cindex Future Plans
We will continue building on the existing netCDF access library for
Unidata system software and applications.  We intend to use netCDF
interfaces for earth-referenced image-analysis software, as well as for
the output of decoders for a wide variety of meteorological and
oceanographic data.

A collection of netCDF operators will be made available that provide an
algebra of useful operations on generic scientific data stored in netCDF
files.  These include selectors that will extract subsets of variables
or reduce the dimensionality of a netCDF file; constructors that will
merge netCDF files, combine variables, or increase dimensionality;
graphics generators that read netCDF files and produce graphical output;
mathematical operators; and specialized data converters to convert
units, convert to or from standard archive forms, or to convert to a
canonical form for comparison.  By composing these fundamental
operators, users will have a wide variety of capabilities.

We plan to extend the netCDF library in an upward-compatible way to
support netCDF servers on a network.  Applications programs, as clients
of the netCDF servers, will be able to access cross-sections of data
efficiently, as if it were stored in a local file.  A netCDF server will
have the ability to support virtual netCDF objects that provide
different views of large or remote datasets.  Other servers may also be
capable of transparently providing a netCDF interface to non-netCDF
archives.

@node References, , Future Plans, Introduction
@unnumberedsec References

@enumerate

@item
Fahle, J., @emph{TeraScan Applications Programming Interface}, SeaSpace,
San Diego, California, 1989.
@item
Fulker, D. W., ``The netCDF:  Self-Describing, Portable Files---a Basis
for `Plug-Compatible' Software Modules Connectable by Networks,'' ICSU
Workshop on Geophysical Informatics, Moscow, USSR, August 1988.
@item
Gough, M. L., @emph{NSSDC CDF Implementer's Guide (DEC VAX/VMS) Version
1.1}, National Space Science Data Center, 88-17, NASA/Goddard Space
Flight Center, 1988.
@item
Raymond, D. J., ``A C Language-Based Modular System for Analyzing and
Displaying Gridded Numerical Data,'' Journal of Atmospheric and Oceanic
Technology, @strong{5}, 501-511, 1988.
@item
Rew, R. K. and G. P. Davis, ``The Unidata netCDF: Software for
Scientific Data Access,'' @emph{Sixth International Conference on Interactive
Information and Processing Systems for Meteorology, Oceanography, and
Hydrology}, Anaheim, California, American Meteorology Society, February 1990.
@item
Rew, R. K. and G. P. Davis, ``NetCDF: An Interface for
Scientific Data Access,'' @emph{Computer Graphics and Applications},
IEEE, July 1990.
@item
Treinish, L. A. and M. L. Gough, ``A Software Package for the Data
Independent Management of Multi-Dimensional Data,'' @emph{EOS
Transactions}, American Geophysical Union, @strong{68}, 633-635, 1987.
@item
Sun Microsystems, ``External Data Representation Standard: Protocol
Specification,'' RFC 1014; Information Sciences Institute, May 1988.
@end enumerate

@node Components, Data, Introduction, Top
@chapter Components of a netCDF File

@cindex netCDF components
@cindex netCDF dimensions
@cindex netCDF variables
@cindex netCDF attributes
A netCDF file has @dfn{dimensions}, @dfn{variables}, and
@dfn{attributes}.  These components can be used together to capture the
meaning of data and relations among data fields in a scientific data set.

@cindex CDL
@cindex CDL example
@cindex network Common Data Form Language (CDL)
@vindex NC_UNLIMITED
We will use a small netCDF example to illustrate the concepts of netCDF
dimensions, variables, and attributes.  The notation used to describe
this simple netCDF object is called CDL (network Common Data form
Language).  It provides an easily comprehended text version of the
structure and contents of a binary netCDF file:
@example
@group
netcdf example_1 @{  // example of CDL notation for a netCDF file

dimensions:          // all the dimensions are declared first
        lat = 5, lon = 10, level = 4, time = unlimited;

variables:           // variable types, names, and shapes
        float   z(time,level,lat,lon);
        double  p(time,level,lat,lon), t(time,level,lat,lon);
        double  rh(time,lat,lon);
        int     lat(lat), lon(lon), level(level);
        short   time(time);
                     // variable attributes
        lat:units       = "degrees north";      
        lon:units       = "degrees east";
        t:long_name     = "temperature";
        t:units         = "degrees Celsius";
        t:valid_range   = -100.0, 100.0;       // min and max
        rh:long_name    = "relative humidity";
        time:units      = "hours from base_time";
                     // global attributes
        :source = "NWS";
        :base_time = "88/10/25 12:00:00";

data:                // optional data assignments
        level   = 100, 500, 750, 1000;
        lat     = 20, 30, 40, 50, 60;
        lon     = -160,-140,-118,-96,-84,-52,-45,-35,-25,-15;
        time    = 0, 12;
        rh      = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 .1,.1,.1,.1,.1,.1,.1,.1,.1,.1,
                 .2,.2,.2,.2,.2,.2,.2,.2,.2,.2,
                 .3,.3,.3,.3,.3,.3,.3,.3,.3,.3,
                 .4,.4,.4,.4,.4,.4,.4,.4,.4,.4;
@}
@end group
@end example

@findex ncdump
@findex ncgen
@cindex CDL notation
The CDL notation for a netCDF file can be generated automatically by
using @code{ncdump}, a utility program described later.  Another netCDF
utility, @code{ncgen}, generates a netCDF file (or optionally C or
FORTRAN source code containing calls needed to produce a netCDF file)
from CDL input.  It is not necessary to learn much about CDL notation
to use the netCDF library; we use it in this document as a concise way of
presenting netCDF examples.

The CDL notation will be explained more fully as we describe the
components of a netCDF file.  For now, note that all CDL statements are
terminated by a semicolon.  Spaces, tabs, and newlines can be used freely
for readability.  Comments in CDL follow the characters @kbd{//} on any
line.  A CDL description of a netCDF file takes the form
@example
@group
  netCDF @var{name} @{
    dimensions: @dots{}
    variables: @dots{}
    data: @dots{}
  @}
@end group
@end example
@noindent
where the @var{name} is used only as a default in constructing the name
of the file generated by the @code{ncgen} utility.  The CDL description
consists of three optional parts, introduced by the keywords
@code{dimensions}, @code{variables}, and @code{data}.  netCDF dimension
declarations appear after the @code{dimensions} keyword, netCDF
variables and attributes are defined after the @code{variables} keyword,
and variable data assignments appear after the @code{data} keyword.

@menu
* What Are Dimensions?::  The components of and operations on netCDF
                          dimensions.

* What Are Variables?::  The components of and operations on netCDF
                          variables.

* What Are Attributes?::  The components of and operations on netCDF
                          attributes.
@end menu

@node What Are Dimensions?, What Are Variables?, , Components
@section Dimensions

@cindex dimensions
A netCDF dimension is a named integer used to specify the shape of one
or more of the multidimensional variables contained in a netCDF file.
A dimension may be used to represent a real physical dimension, for
example, time, latitude, longitude, or height.  A dimension might also be
used to index more abstract quantities, for example, color-table entry
number, instrument number, station-time pair, or model-run ID.

@cindex dimension names
@cindex dimension size
@cindex netCDF names
@cindex CDL names
@cindex unlimited dimension
@cindex record dimension
@cindex record variables
Every netCDF dimension has both a @dfn{name} and a @dfn{size}.  A
dimension name is an arbitrary sequence of alphanumeric characters
(including the underscore character, @kbd{_}) beginning with a letter.
Case is distinguished in netCDF names.  A dimension size is an arbitrary
positive integer, except that one dimension in a netCDF file can have
the size @code{UNLIMITED}.  Such a dimension is called the
@dfn{unlimited dimension} or the @dfn{record dimension}.  A variable
with an unlimited dimension can grow to any length along that dimension.
The unlimited dimension is like a record number in conventional
record-oriented files.

CDL dimension declarations may appear on one or more lines following the
CDL keyword @code{dimensions}.  Multiple dimension declarations on the
same line may be separated by commas.  Each declaration is of the form
@var{name} = @var{size}.

@cindex unlimited dimension
There are four dimensions in the example: @code{lat}, @code{lon},
@code{level}, and @code{time}.  The first three are assigned
fixed sizes; @code{time} is assigned the size @code{UNLIMITED}, which means
it is the @dfn{unlimited} dimension.  A netCDF file can have at most one
unlimited dimension, but need not have any.

There are several uses for netCDF dimensions:
@itemize @bullet
@item
specifying the shapes and sizes of variables,
@item
identifying and relating variables that are defined on a common grid,
and
@item
providing a way to define coordinate systems.
@end itemize
We discuss each of these uses below.

@menu
* Specifying Variable Shapes::  Using Dimensions to Specify the Shapes
                                of Variables

* Relating Variables::          Using Dimensions to Relate Variables

* Defining Coordinates::        Using Dimensions to Define Coordinates
@end menu

@node Specifying Variable Shapes, Relating Variables, , What Are Dimensions?
@subsection Using Dimensions to Specify Variable Shapes

@cindex specifying variable shapes
The basic unit of named data in a netCDF is a @dfn{variable}.  In
general, a variable is a multidimensional object that has, among other
characteristics, a @dfn{shape}, which is defined by the number, order,
and sizes of its dimensions.  When a netCDF variable is defined, the
number and order of the dimensions that define its shape are specified.
Hence you must first create the necessary dimensions before creating a
netCDF variable that uses them.

It is possible to use the same dimension more than once in specifying a
variable shape, for example @code{var(dim, dim)}, but it does not make
much sense to do this; it is contrary to the intuitive meaning of a
physical dimension.  A variable that has two dimensions that happen to
be the same size is more accurately modeled by using two dimensions with
different names but the same size.

@node Relating Variables, Defining Coordinates, Specifying Variable Shapes, What Are Dimensions?
@subsection Using Dimensions to Relate Variables

@cindex relating variables
Two dimensions may have the same size, perhaps by coincidence, without
being related in any other way.  Dimension names provide a way to distinguish
dimensions regardless of size.

@cindex variables
Variables are related by the dimensions they share.  For example, if two
variables are defined with the same dimensions, they might represent
observations or model output for the same set of points.  In the example
netCDF file, variables @code{z}, @code{t}, and @code{p} have exactly the
same dimensions, so they refer to different variables defined at the
same points on a four-dimensional space-time grid.  The variable
@code{rh} does not have @code{level} as a dimension, perhaps because it is only
defined for a single level.

@node Defining Coordinates, , Relating Variables, What Are Dimensions?
@subsection Using Dimensions to Define Coordinate Systems

@cindex defining coordinate systems
@cindex coordinates
@cindex coordinate variables
Besides serving as sizes for integer indexes to multidimensional
variables, dimensions may be used to define coordinate systems for
variable data.  To do this, create a variable with the same name as a
dimension and specify coordinate values for that variable.  A variable
should only be given the same name as a dimension in a netCDF if it is
intended to be used as a @dfn{coordinate} variable.  Such variables are
indexed by the dimension for which they provide coordinate values, for
example, @code{lat(lat)}.

It is not necessary to provide a coordinate variable for each dimension;
if no such variable is defined, the coordinate values of the dimension
are assumed to be 0, 1, 2, @dots{} (for C programs) or 1, 2, 3, @dots{}
(for FORTRAN programs).  Although the C and FORTRAN interfaces support
different conventions for index numbering, there is no difference
between the actual netCDF files written by C and FORTRAN programs.
Programs written in either language can be used to access data written
by programs using the other interface.

In the CDL example, each dimension has an associated coordinate
variable with the same name as the dimension.  The four values of the
@code{level} index, 0, 1, 2, 3, (1, 2, 3, 4 in FORTRAN) are related in
coordinate-like fashion to the four values (100, 500, 750, 1000) of the
@code{level} variable.  Note that there is no requirement that
coordinates be equally spaced or increasing.  It would not make much
sense for two coordinate values to be the same, but the meaning of
coordinate variables is enforced only by conventions of application
packages and utilities, not by the netCDF interface.

@node What Are Variables?, What Are Attributes?, What Are Dimensions?, Components
@section Variables
@cindex variables

@cindex data types
@cindex variable shape
@cindex shape of a netCDF variable
@cindex variable attributes
@cindex variable data values
A @dfn{variable} represents a multidimensional array of values of the
same type.  A variable has a name, a data type, and a shape described by
its list of dimensions, all of which are specified when the variable is
created.  Each variable may also have data values and associated
attributes, which may be added or changed after the variable is created.
Variables are used to store the bulk of the data in a netCDF file, and
are the primary component used by utilities to identify sub-parts of a
netCDF file.

@cindex variable name
Like a dimension name, a variable name is an arbitrary sequence of
alphanumeric characters (including @kbd{_}) beginning with a letter.  Case
is distinguished in variable names.  Long names help to make
a netCDF file self-documenting, but ancillary information about a
variable is better stored in variable @dfn{attributes} (discussed below)
than encoded as part of the name.

@cindex data types
@cindex variable data types
@cindex NC_BYTE type specifier
@cindex NC_CHAR type specifier
@cindex NC_SHORT type specifier
@cindex NC_LONG type specifier
@cindex NC_FLOAT type specifier
@cindex NC_DOUBLE type specifier
@cindex byte CDL type
@cindex char CDL type
@cindex short CDL type
@cindex long CDL type
@cindex float CDL type
@cindex double CDL type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
A variable data type is one of a small set of netCDF @dfn{types} that
have the names @code{NC_BYTE}, @code{NC_CHAR}, @code{NC_SHORT},
@code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE} in the C interface
and the corresponding names @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT},
@code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE} in the
FORTRAN interface.  In the CDL notation, these types are given the
simpler names @code{byte}, @code{char}, @code{short}, @code{long},
@code{float}, and @code{double}.  @code{int} may be used as a synonym
for @code{long} and @code{real} may be used as a synonym for
@code{float} in the CDL notation.  We will postpone a discussion of the
exact meaning of each of the types until the discussion of @dfn{data},
below.  For now, it suffices to know that the choice of the type used to
represent variable data depends on the range of values it can have, the
precision to which values are known, and the number of bits required to
represent the variable in a netCDF file on disk.

@cindex unlimited dimension
@cindex scalar variables
The shape of a variable is specified by its list of dimensions.  If a
variable has an unlimited dimension, that dimension must appear
first in the list of dimensions in CDL.  It is possible to define variables
with no dimensions, also called @dfn{scalar} variables.  There are no
scalar variables in the example netCDF file.

@cindex CDL variable declarations
CDL variable declarations appear after the @code{variables} keyword in
a CDL unit.  They have the form
@display
     @i{type} @i{variable_name}  ( @i{dim_name_1, dim_name_2, @dots{}} ) ;
@end display
@noindent
for variables with dimensions, or
@display
     @i{type} @i{variable_name} ;
@end display
@noindent
for scalar variables.

@cindex record variables
@cindex variable size
In the CDL example there are eight variables.  As discussed above, four
of these are coordinate variables for dimensions.  The remaining
variables, @code{z}, @code{t}, @code{p}, and @code{rh} are meant to contain
the ``real'' data in this netCDF object.  Each of these variables has the
unlimited dimension @code{time} as its first dimension, so they
are called @dfn{record} variables.  A variable that is not a record
variable has a fixed size (number of data values) given by the product
of its dimensions.  A record variable has a current size, given by
the product of the maximum record written so far and the other
dimensions of the variable.  Only record variables may grow after they
are defined.

@node What Are Attributes?, , What Are Variables?, Components
@section Attributes

@cindex attributes
@cindex metadata
@cindex database management systems
A netCDF @dfn{attribute} is meant to contain information about a netCDF
variable or about an entire netCDF file.  This information is
@dfn{metadata}, or data about data, analogous to the information stored in
data dictionaries and schema in conventional database systems.  An
attribute has an associated variable, a name, a data type, a length, and
a value.  Individual attributes are identified by specifying a variable
and an attribute name.

@cindex variable attributes
Each attribute is associated with a single variable when it is created.
Attributes for different variables may differ in data type, length, and
values even though they share the same name.  

@cindex global attributes
A @dfn{global} attribute is one that applies to the whole netCDF rather
than any particular variable.  Global attributes are defined and
accessed similarly to variable attributes; the details for defining
global attributes in the CDL notation and in the netCDF procedural
interface are presented later.

@cindex attribute names
@cindex conventional attributes
@cindex generic applications
@cindex units attribute
Attribute names follow the same rules as dimension and variable names.
Providing meaningful names for attributes is important, but using agreed
on conventional names is also required if generic applications and
utility programs will be used on a netCDF file.  For example, every
variable for which units make sense should have a @code{units} attribute
defined, so the units can be printed in labels.  Furthermore, if the
netCDF file is ever to be used as input to a generic units-converter
program, the values of the @code{units} attributes should be expressed
in a conventional form as a character string that can be interpreted by
that program.

@cindex attribute type
The type of an attribute is specified when it is created.  The types
permitted for attributes are exactly the same as the netCDF data types
used in creating variables.  Attributes with the same name for different
variables should sometimes be of different types.  For example, the
attribute @code{valid_max} specifying the maximum valid data value for a
variable of type @code{long} should be of type @code{long}, whereas the
attribute @code{valid_max} for a variable of type @code{double} should
instead be of type @code{double}.

@cindex attribute length
@cindex attribute values
@cindex string-valued attributes
In addition to specifying the associated variable, attribute name, and
type, the length and value of an attribute must also be specified when it is
created.  The information in an attribute is represented by either a single
value (length 1) or a vector of values of the same type.  Since
``character string'' is not a basic netCDF data type, string-valued
attributes have a vector of characters as their value, with a length
equal to the length of the character string.

@cindex attributes
@cindex dimensions
@cindex variables
Attributes are more dynamic than variables or dimensions; they
can have their type, length, and values changed after they are created.
For example, an attribute @code{max_value} might store the maximum value
seen so far for a record variable, and might be updated every time a new
record is written.

@cindex CDL notation
@cindex variable attributes
@cindex global attributes
@cindex attribute type
@cindex attribute length
The CDL notation for defining an attribute is
@display
    @i{variable_name:attribute_name} = @i{list_of_values} ;
@end display
@noindent
for a variable attribute, or
@display
    @i{:attribute_name} = @i{list_of_values} ;
@end display
@noindent
for a global attribute.  The type and length of each attribute are not
explicitly declared in CDL; they are derived from the values assigned to
the attribute.  All values of an attribute must be of the same type.
The notation used for constant values of the various netCDF types is
discussed later.

In the example netCDF, @code{units} is an attribute for the variable
@code{lat} that has a length 13-character array value @samp{degrees north}.
@code{valid_range} is an attribute for the variable @code{t} that has
length 2 and values @samp{-100.0} and @samp{100.0}.

@cindex global attributes
Two global attributes---@code{source} and @code{base_time}---are defined
for the example netCDF.  Both are character arrays intended for
documenting the data.  Real netCDF files typically have more global
attributes to document the origin, history, accuracy, and other
characteristics of the data.

@menu
* Attribute Conventions::    Conventions for Commonly Used Attributes

* Attributes and Variables:: Differences Between Attributes and Variables
@end menu

@node    Attribute Conventions, Attributes and Variables, ,What Are Attributes?
@comment  node-name,  next,  previous,  up
@subsection Attribute Conventions

@cindex attribute conventions
@cindex conventional attributes
@cindex generic applications
Generic applications that take netCDF files as input will, by
convention, expect certain variable and global attributes.  If you want
to be able to use these generic applications with your files, you
should use the following conventional names for these commonly used
attributes:

@cindex units attribute
@table @code
@item units
A character array giving the units used for the variable's data.  A
standard for conventional ways to name units in each specific discipline
should be used, if available.  Unidata is compiling a suggested standard
for data in the atmospheric sciences.
@cindex long_name attribute
@cindex variable name
@item long_name
A long descriptive name for labelling plots, for example.  If a variable
has no @code{long_name} attribute assigned, the variable name will be
used as a default.
@cindex valid_range attribute
@item valid_range
An array of two numbers specifying the minimum and maximum valid values
for this variable.  The type of each @code{valid_range} attribute should
match the type of its variable.
@cindex valid_min attribute
@cindex valid_max attribute
@item valid_min
@itemx valid_max
One or both of these may be used instead of @code{valid_range}; this
handles the case where it only makes sense to bound the data below
or above.
@cindex scaling data
@cindex scale_factor attribute
@item scale_factor
If present for a variable, the data are to be multiplied by this factor
after the data is read by the application that accesses the data.
@cindex data packing
@cindex data compression
@cindex data resolution
@cindex add_offset attribute
@item add_offset
If present for a variable, this number is to be added to the data after
it is read by the application that accesses the data.  If
both @code{scale_factor} and @code{add_offset} attributes are present,
the data are first scaled before the offset is added.
The attributes @code{scale_factor} and @code{add_offset} can be used
together to provide simple data compression for low-resolution
data to be stored as small integers in a netCDF file.  When scaled data
is written, the application should first subtract the offset and then
divide by the scale factor.

@cindex missing values
@cindex fill values
@cindex missing_value attribute
@item missing_value
If present for a variable, this value is considered to be a special
value that indicates missing data.  Hence an application that is
displaying the data should ignore all data points with this value.  The
missing value should be outside the range specified by
@code{valid_range} for a variable.  It is not necessary to define your
own @code{missing_value} attribute for a variable if the default
@dfn{fill value} for the type of the variable is adequate.
@xref{Missing Values}.  If you define your own @code{missing_value}
attribute for a floating point type, use an integer less than 1000000 in
absolute value to avoid machine precision problems.
@cindex data formats
@cindex C_format attribute
@item C_format
A character array for the format that should be used to print values for
this variable by C applications.
@cindex FORTRAN_format attribute
@item FORTRAN_format
A character array for the format that should be used to print values for
this variable by FORTRAN applications.
@cindex title attribute
@item title
A global attribute that is a character array providing a succinct
description of what is in the data set.
@cindex recording data history
@cindex generic applications
@cindex generic filters
@cindex history attribute
@item history
A global attribute that is a character array with a line for each
invocation of a program and arguments that were used to derive the file.
Well-behaved generic netCDF filters (programs that take netCDF files as
input and produce netCDF files as output) will automatically append
their name and the parameters with which they were invoked to the global
history attribute of an input netCDF file.
@end table
Note that more attributes may be added to a netCDF file long after it is first
defined, so you don't have to anticipate all potentially useful attributes.

@node   Attributes and Variables, , Attribute Conventions, What Are Attributes?
@subsection Differences between Attributes and Variables

@cindex variables
@cindex attributes
@cindex differences between attributes and variables
@cindex metadata
In contrast to variables, which are intended for data, attributes are
intended for metadata.  Typically the data in variables of an open
netCDF will reside on disk, because the data are too large to fit in
memory all at once.  In contrast, the total amount of metadata
associated with a netCDF object and stored in its attributes is
typically small enough to be memory-resident.

Another difference between attributes and variables is that variables
may be multidimensional.  Attributes are all either scalars
(single-valued) or vectors (a single, fixed dimension).

@cindex variable values
@cindex attribute values
Variables are created with a name, type, and shape before they are assigned
data values, so a variable may exist with no values.  The value of an
attribute must be specified when it is created, so no attribute ever
exists without a value.

@cindex units attribute
A variable may have attributes, but an attribute cannot have attributes.
Attributes assigned to variables may have the same units as the variable
(for example, @code{valid_range}) or have no units (for example,
@code{scale_factor}).  If you want to store data in a netCDF that
requires units different from those of the associated variable, it is
better to use a variable than an attribute.  More generally, if data
require ancillary data to describe them, are multidimensional, require
any of the defined netCDF dimensions to index their values, or require a
significant amount of storage, the data should be represented using
variables rather than attributes.

@node Data, Usage, Components, Top
@chapter Data
This chapter discusses the six primitive netCDF data types, the kinds of
data access supported by the netCDF interface, and how data structures other
than multidimensional arrays may be implemented in a netCDF file.

@menu
* Data Types::	    The six basic netCDF data types.

* Data Access::     Direct access, hyperslab access, and record access.

* Data Structures:: Representing other structures with netCDF arrays.
@end menu

@node Data Types, Data Access, , Data
@section netCDF Data Types

@cindex netCDF data types
@cindex byte type
@cindex char type
@cindex short type
@cindex long type
@cindex float type
@cindex double type
@cindex primitive netCDF types
@cindex ASCII characters
@cindex IEEE floating-point
The current set of primitive types supported by the netCDF interface are
@table @code
@item byte
used for eight-bit data, especially good for saving space when
only a few values are possible or resolution is low.
@item character
currently synonymous with @code{byte}, intended for
representing text strings as arrays of ASCII characters.
@item short
16-bit integers.
@item long
32-bit integers.
@item float
32-bit IEEE floating-point.
@item double
64-bit IEEE floating-point.
@end table

@cindex unsigned
@cindex CDL reserved words
Except for the added data-type @code{byte} and the lack of
@code{unsigned}, netCDF supports the same primitive data types as C.  The
names for the primitive data types are reserved words in CDL, so the
names of variables, dimensions, and attributes must not be type names.
Whether byte, short, or long data is interpreted as signed or unsigned
is not part of the netCDF interface; since no netCDF operations depend
on the sign or order of variable data, you are free to interpret a byte,
for example, as holding values between 0 and 255 or between -128 and
127.  For convenience, short and long constants are interpreted as
signed in the CDL notation.

@cindex XDR
These types were chosen because they are familiar to C and FORTRAN
programmers, they have well-defined external representations independent
of any particular computers (using XDR), and they are sufficient for
providing a reasonably wide range of trade-offs between data precision
and number of bits required for each datum.

@cindex future changes planned
Additional primitive types may be added in the future, but only in a way
that is compatible with existing programs and files.  For example,
@code{hyperlong} for 64-bit integers will eventually be needed, along
with a new type for multibyte characters, but these can both be added
without affecting existing netCDF files or applications, and with
only minor changes required for generic applications that will support
them.

@node Data Access, Data Structures, Data Types , Data
@section Data Access

The netCDF interface supports direct (random) access to single data
values, direct access to an arbitrary hyperslab of data for a single
variable, and record-oriented access to data for a single variable (as a
special case of hyperslab access) in an open netCDF file.

To directly access a single data value, you specify a netCDF file, a
variable, and a multidimensional index for the variable.  Files are not
specified by name every time you want to access data, but instead by a
small integer obtained when the file was first created or opened.
Similarly, variables are not specified by name for every data access
either, but by variable IDs, small integers used to identify variables
in a netCDF file.

@cindex hyperslabs
@cindex hyperslab corner
@cindex hyperslab edge lengths
@cindex subscript order
@cindex index order
@cindex data order
Data in a netCDF file can be accessed as single values or as
@dfn{hyperslabs}.  A hyperslab is a kind of generalized piece of a
multidimensional variable that is specified by giving the indices of a
corner point and a list of edge lengths along each of the dimensions of
the variable.  The corner point specified must be the one with the
smallest indices, that is the one closest to the origin of the variable
index space.  The block of data values returned (or written) has the
last dimension of the variable varying fastest, and the first dimension
varying most slowly in the C interface.  For FORTRAN, the order is
reversed, with the first dimension of the variable varying fastest and
the last dimension varying most slowly.  These ordering conventions
correspond to the customary order in which multidimensional variables
are stored in C and FORTRAN.

@cindex hyperslab access example
As an example of hyperslab access, assume that in the first example
netCDF you wish to read all the data for the @code{z} variable at the
second (500-mb) level, and assume that there are currently three records
(@code{time} values) in the netCDF file.  Recall that the dimensions are
defined as:
@example
        lat = 5, lon = 10, level = 4, time = unlimited;
@end example
@noindent
and the variable @code{z} is declared as
@example
        float   z(time, level, lat, lon);
@end example
@noindent
in the CDL notation.

In C, this corresponds to
@example
#define LATS  5
#define LONS 10
#define LEVELS 4
#define TIMES 3                 /* currently */
    @dots{}
float   z[TIMES*LEVELS*LATS*LONS];
@end example
@noindent
to keep the data in a one-dimensional array, or
@example
    @dots{}
float   z[TIMES][LEVELS][LATS][LONS];
@end example
@noindent
using a multidimensional array declaration.

In FORTRAN, the dimensions are reversed from the CDL declaration with the
first dimension varying fastest and the record dimension as the last
dimension of a record variable, as in
@example
@group
      PARAMETER (LATS=5, LONS=10, LEVELS=4, TIMES=3)
         @dots{}
      REAL Z(LONS, LATS, LEVELS, TIMES)
@end group
@end example

@cindex hyperslab corner
@cindex hyperslab edge lengths
@cindex subscript order
@cindex index order
@cindex data order
Then the corner should be (0, 1, 0, 0) in C---or (1, 1, 2, 1) in
FORTRAN---because you want to start at the beginning of each of
the @code{time}, @code{lon}, and @code{lat} dimensions, but you
want to begin at the second value of the @code{level} dimension.  The
edge lengths should be (3, 1, 5, 10) in C---or (10, 5, 1, 3) in
FORTRAN---since you want to get data for all three @code{time} values,
only one @code{level} value, all five @code{lat} values, and all 10
@code{lon} values.  You should expect to get a total of 150 float values
returned (3 * 1 * 5 * 10), and should provide enough space in your array
for this many.  The order in which the data will be returned is with the
last dimension, @code{lon}, varying fastest for C, or with the first
dimension, @code{LON}, varying fastest for FORTRAN:
@example
@group
           C               FORTRAN

     z[0][1][0][0]      z(1, 1, 2, 1)
     z[0][1][0][1]      z(2, 1, 2, 1)
     z[0][1][0][2]      z(3, 1, 2, 1)
     z[0][1][0][3]      z(4, 1, 2, 1)

        @dots{}                  @dots{}

     z[2][1][4][7]      z( 8, 5, 2, 3)
     z[2][1][4][8]      z( 9, 5, 2, 3)
     z[2][1][4][9]      z(10, 5, 2, 3)
@end group
@end example

@cindex language interfaces
@cindex data order
@cindex order of data
Note that the different dimension orders for the C and FORTRAN
interfaces do not reflect a different order for values stored on the
disk, but merely different orders supported by the procedural interfaces
to the two languages.  In general, it does not matter whether a netCDF
file is written using the C or FORTRAN interface; netCDF files written
from either language may be read by programs written in the other
language.

@cindex records
@cindex record-oriented access
@cindex record variables
To perform conventional record-oriented access, you specify a netCDF
file, a record variable (one defined with an unlimited dimension),
and use the record number as the value of the first dimension (last
dimension in FORTRAN), using hyperslab access to get the record of
values.
@cindex efficiency
@cindex performance
@cindex order of dimensions
@cindex data order
@cindex representation on disk
When efficiency is a concern, you should keep in mind the order in which
netCDF data is written on the disk, since the best I/O performance is
achieved by reading or writing contiguous data.  All variable data is
ordered with the last dimension for each variable varying fastest in the
C interface, or the slowest in the FORTRAN interface.  This means that
for record variables in particular, at least one disk access per record
will be required for reading a value from each record.  Hence reading a
hyperslab that takes one value out of each record will require as many
disk accesses as the number of values requested.  For writing, the
situation is even worse, since each record must first be read and then
rewritten to change a single value within a record.  If you have a
choice about the order in which data is accessed or the order of the
dimensions that define the shape of a variable, try to choose these two
orders in harmony to avoid needless inefficiency.

@node Data Structures, , Data Access, Data
@section Data Structures
@cindex data structures
@cindex sparse matrices
@cindex trees
@cindex linked lists
@cindex pointers
@cindex XDR
The only kind of data structure directly supported by the netCDF
abstraction is a collection of multidimensional variables with attached
vector attributes.  The netCDF is not particularly well-suited for
storing linked lists, trees, sparse matrices, or other kinds of data
structures requiring pointers.  The underlying XDR library on which
netCDF is implemented is quite suitable for storing and retrieving
arbitrary data structures in a network-transparent way, but such
structures will no longer be self-describing unless you encode
information about the structure with the data.
@cindex index variables
It is possible to build other kinds of data structures from sets of
multidimensional arrays by adopting various conventions regarding the
use of data in one array as pointers into another array.  The netCDF
library won't provide much help or hindrance with constructing such data
structures, but it is possible to use attributes to name associated
index variables.  For example, a variable attribute such as
@samp{array_index_var = "v_index"} attached to one variable may provide
the name of another associated variable to be used as an index for fast
retrieval by value.

@node Usage, File Operations, Data, Top
@chapter Use of the netCDF Library

@cindex netCDF library use
@cindex common netCDF calls
@cindex typical netCDF calls
It is not necessary to know about all the netCDF modules to make use of
the netCDF library.  If you are creating a netCDF file, only a handful
of routines are required to define the necessary dimensions, variables,
and attributes, and to write the data to the netCDF file.  Similarly, if
you are writing software to access data stored in a particular netCDF
object, only a small subset of the netCDF library is required to open
the netCDF file and access the data.  Only authors of generic
applications that access arbitrary netCDF files and write out
transformed netCDF files need to be familiar with the whole netCDF
library.  In this chapter we provide templates of common sequences of
netCDF subroutine calls needed for the typical uses.  Full argument
lists for the procedures and subroutines are described in later
chapters.

@menu
* Creating a netCDF File::     How to create a new netCDF file.

* Reading with Known Names::   How to read a netCDF file with known names.

* Reading with Unknown Names:: How to read a generic netCDF.

* Adding Components::          How to add new dimensions, variables, and
                               attributes.

* Error Handling::             How to handle errors.
@end menu

@node Creating a netCDF File, Reading with Known Names, , Usage
@section Creating a netCDF File

@cindex netCDF file creation
@cindex creating a netCDF file
The typical sequences of C netCDF calls used to create a new netCDF file
is as follows, where for clarity we only present the name of the
routines, omit all declarations, parameters and error checking, and use
@code{@dots{}} to represent arbitrary sequences of other statements:

@findex nccreate
@findex ncdimdef
@findex ncvardef
@findex ncattput
@findex ncendef
@findex ncvarput
@findex ncclose
@example
    nccreate      /* create netCDF file: enter define mode */
         @dots{}
       ncdimdef   /* dimension definitions: from name and size */
         @dots{}
       ncvardef   /* variable definitions: from name, type, dimensions */
         @dots{}
       ncattput   /* attribute put: assign attribute values */
         @dots{}
    ncendef       /* end definitions: leave define mode */
         @dots{}
    ncvarput      /* variable put: provide values for variables */
      @dots{}
    ncattput      /* attribute put: change attribute values */
      @dots{}
    ncclose       /* close: save new netCDF file */
@end example

In FORTRAN, the corresponding sequence looks like this:
@findex NCCRE
@findex NCDDEF
@findex NCVDEF
@findex NCAPT
@findex NCAPTC
@findex NCENDF
@findex NCVPT
@findex NCVPTC
@findex NCCLOS
@example
    CALL NCCRE              ! create netCDF file: enter define mode
         @dots{}
       CALL NCDDEF          ! define dimensions: from name and size
         @dots{}
       CALL NCVDEF          ! define variables: from name, type, dimensions
         @dots{}
       CALL NCAPT or NCAPTC ! attribute put: assign attribute values
         @dots{}
    CALL NCENDF             ! end definitions: leave define mode
         @dots{}
    CALL NCVPT or NCVPTC    ! variable put: provide values for variables
      @dots{}
    CALL NCAPT or NCAPTC    ! attribute put: change attribute values
      @dots{}
    CALL NCCLOS             ! close: save new netCDF file
@end example
@noindent
The FORTRAN interface provides two subroutines for defining attributes
and providing values for variables, depending on whether a numeric or
character string value is used.  The FORTRAN template indicates that
either of these subroutines could be called.

@cindex define mode
@cindex data mode
@cindex dimensions
@cindex variables
@cindex attributes
Only one call is needed to begin creating a netCDF file, at which
point you will be in the first of two netCDF @dfn{modes}.  When
accessing a netCDF, you are either in @dfn{define mode} or @dfn{data
mode}.  In define mode, you can create dimensions, variables, and new
attributes, but you cannot read or write variable data.  In data mode,
you can access data and change existing attributes, but you are not
permitted to create new dimensions, variables, or attributes.

@cindex attributes
@cindex variables
@cindex dimensions
@cindex define mode
@findex ncdimdef
@findex NCDDEF
@findex ncvardef
@findex NCVDEF
@findex ncattput
@findex NCAPT
@findex NCAPTC
@findex ncendef
@findex NCENDF
One call to @code{ncdimdef} (or @code{NCDDEF}) is needed for each
dimension created.  Similarly, one call to @code{ncvardef} (or
@code{NCVDEF}) is needed for each variable creation, and one call to
@code{ncattput} (or @code{NCAPT} or @code{NCAPTC}) is needed for each
attribute defined and assigned a value.  The only way to leave define
mode and enter data mode is by a call to @code{ncendef} (or
@code{NCENDF}).

@cindex data mode
@cindex attributes
@cindex variables
@findex ncvarput1
@findex NCVPT1
@findex NCVPTC1
@findex ncvarput
@findex NCVPT
@findex NCVPTC
Once in data mode, you can add new data to variables, change old values,
and change values of existing attributes (so long as the attribute
changes do not require more storage space for the attribute).  Single
values are written to a variable with @code{ncvarput1} (or @code{NCVPT1}
or @code{NCVPTC1}); while arbitrary hyperslabs of data are written using
@code{ncvarput} (or @code{NCVPT} or @code{NCVPTC}) instead.

@cindex data loss
@cindex abnormal termination
@cindex closing files
@cindex attributes
@cindex variables
@cindex performance
@cindex efficiency
@findex ncclose
@findex NCCLOS
@findex ncsync
@findex NCSNC
Finally, you should explicitly close all open netCDF
files on which you are writing by calling @code{ncclose} (or
@code{NCCLOS}) before the program exits.  If a program terminates
abnormally with netCDF files open for writing, you may lose one or more
records of the most recently written record variable data as well as any
attribute changes since the last call to @code{ncsync} (or
@code{NCSNC}).  It is possible to reduce the chance of losing data due
to abnormal termination by explicitly calling @code{ncsync}
(@code{NCSNC}) after every write to netCDF variables or change to
attribute values.  This can be expensive in computer resources, so
such calls should ordinarily be omitted unless they are really needed.

@node Reading with Known Names, Reading with Unknown Names, Creating a netCDF File, Usage
@section Reading a netCDF File with Known Names

@cindex known names
@cindex reading a netCDF file
@cindex generic applications
If you know the names of the dimensions, variables, and attributes in a
netCDF file, you can write calls to read data from the file; you don't
need to include the ``inquire'' calls that determine what the
dimensions, variables, and attributes are.  If you employ such knowledge
about particular netCDF files, the program you write will lack
generality.  It will only work with files that have the assumed names
and structure, so you will be losing some of the advantages of using the
netCDF interface.  However, you may be writing software that expects the
user or some other program to supply variable or dimension names,
perhaps as subroutine or command line arguments.  In that case, the
resulting program could be quite general.

When you know the names of some variables of interest and their
dimensions, the order of typical C calls to read data from those
variables in a netCDF file is:

@findex ncopen
@findex ncdimid
@findex ncvarid
@findex ncattget
@findex ncvarget
@findex ncclose
@example
    ncopen           /* open existing netCDF */
      @dots{}
    ncdimid          /* get dimension IDs to use in accessing data */
      @dots{}
    ncvarid          /* get variable IDs */
      @dots{}
    ncattget         /* get attribute values, if needed */
      @dots{}
    ncvarget         /* get values of variables */
      @dots{}
    ncclose          /* close netCDF */
@end example

In FORTRAN, the corresponding sequence looks like this:
@findex NCOPN
@findex NCDID
@findex NCVID
@findex NCAGT
@findex NCAGTC
@findex NCVGT
@findex NCVGTC
@findex NCCLOS
@example
    CALL NCOPN            !  open existing netCDF 
      @dots{}
    CALL NCDID            !  get dimension IDs to use in accessing data 
      @dots{}
    CALL NCVID            !  get variable IDs 
      @dots{}
    CALL NCAGT or NCAGTC  !  get attribute values, if needed 
      @dots{}
    CALL NCVGT or NCVGTC  !  get values of variables 
      @dots{}
    CALL NCCLOS           !  close netCDF 
@end example

@cindex opening a netCDF file
First, a single call opens the netCDF file, given the file name, and
returns a netCDF ID that is used to refer to the netCDF in all
subsequent calls.  

@cindex dimensions
@cindex dimension IDs
@cindex variables
@cindex variable IDs
@cindex variable data
@cindex efficiency
@cindex performance
@cindex hyperslab access
@findex ncopen
@findex NCOPN
@findex ncvarid
@findex NCVID
@findex ncattget
@findex NCAGT
@findex NCAGTC
@findex ncvarget1
@findex NCVGT1
@findex NCVG1C
@findex ncvarget
@findex NCVGT
@findex NCVGTC
Next, a call to @code{ncopen} (or @code{NCOPN}) for each dimension of
interest gets the dimension ID from the dimension name.  Dimension IDs,
like netCDF IDs, are small integers used to refer to dimensions in
subsequent calls.  Similarly, each required variable ID is determined
from its name by a call to @code{ncvarid} (or @code{NCVID}).  Once
variable IDs are known, variable attribute values can be retrieved using
the netCDF ID, the variable ID, and the desired attribute name as input
to @code{ncattget} (or @code{NCAGT} or @code{NCAGTC}) for each desired
attribute.  Variable data values can be directly accessed from the
netCDF file with @code{ncvarget1} (or @code{NCVGT1} or @code{NCVG1C})
for single values, or @code{ncvarget} (or @code{NCVGT} or @code{NCVGTC})
for hyperslabs of values.  To minimize the number of disk accesses, you
should remember that the last dimension in C (first dimension in
FORTRAN) varies fastest when using hyperslab access.

@cindex closing a netCDF file
@findex ncclose
@findex NCCLOS
Finally, the netCDF file can be closed with @code{ncclose} (or
@code{NCCLOS}) when you are finished with it to free system
resources.  There is no harm in not closing a file open only for
reading.

@node Reading with Unknown Names, Adding Components, Reading with Known Names, Usage
@section Reading a netCDF File with Unknown Names

@cindex generic applications
@cindex inquire functions
@cindex dimensions
@cindex variables
@cindex attributes
If you want to write generic software (i.e., a program that transposes
specified variables by interchanging specified dimensions) you should
make no assumptions about the dimension and variable names that are not
specified.  In such cases, you must find out about all the dimensions,
variables, and attributes in a netCDF file by calling the inquire
functions.  Four inquire functions get information about a whole netCDF
file, a dimension, a variable, or an attribute.  The following template
illustrates how they are used:
@findex ncopen
@findex ncinquire
@findex ncdiminq
@findex ncvarinq
@findex ncattname
@findex ncattinq
@findex ncattget
@findex ncvarget
@findex ncclose
@example
@group
    ncopen           /* open existing netCDF */
      @dots{}
    ncinquire        /* find out what is in it */
         @dots{}
       ncdiminq      /* get dimension names, sizes */
         @dots{}
       ncvarinq      /* get variable names, types, shapes */
            @dots{}
          ncattname  /* get attribute names */
            @dots{}
          ncattinq   /* get attribute types and lengths */
            @dots{}
          ncattget   /* get attribute values */
            @dots{}
    ncvarget         /* get values of variables */
      @dots{}
    ncclose          /* close netCDF */
@end group
@end example

In FORTRAN, the corresponding sequence looks like this:
@findex NCOPN
@findex NCINQ
@findex NCDINQ
@findex NCVINQ
@findex NCAINQ
@findex NCAGT
@findex NCAGTC
@findex NCVGT
@findex NCVGTC
@findex NCCLOS
@example
@group
    CALL NCOPN                 !  open existing netCDF 
      @dots{}
    CALL NCINQ                 !  find out what is in it 
         @dots{}
       CALL NCDINQ             !  get dimension names, sizes 
         @dots{}
       CALL NCVINQ             !  get variable names, types, shapes 
            @dots{}
          CALL NCANAM          !  get attribute names 
            @dots{}
          CALL NCAINQ          !  get attribute values 
            @dots{}
          CALL NCAGT or NCAGTC !  get attribute values 
            @dots{}
    CALL NCVGT or NCVGTC       !  get values of variables 
      @dots{}
    CALL NCCLOS                !  close netCDF 
@end group
@end example

@findex ncinquire
@findex NCINQ
As in the previous example, a single call opens the existing netCDF
file, returning a netCDF ID.  This netCDF ID is given to the
@code{ncinquire} (or @code{NCINQ}) routine, which returns the number of
dimensions, the number of variables, the number of global attributes,
and the ID of the unlimited dimension, if there is one.

@cindex dimension IDs
@cindex dimensions
@findex ncdiminq
@findex NCDINQ
Dimension IDs are assigned by using consecutive integers (beginning at 0
in C, 1 in FORTRAN).  Also dimensions, once created, cannot be deleted.
Therefore, knowing the number of dimension IDs in a netCDF means knowing
all the dimension IDs: they are the integers 0, 1, 2, @dots{}, (or 1, 2,
3, @dots{} in FORTRAN).  For each dimension ID, a call to the inquire
function @code{ncdiminq} (or @code{NCDINQ}) returns the dimension name
and size.

@cindex variables
@findex ncvarinq
@findex NCVINQ
Like dimension IDs, variable IDs are also 0, 1, 2, @dots{}, (or 1, 2, 3,
@dots{} in FORTRAN).  These can be used in @code{ncvarinq} (or
@code{NCVINQ}) calls to find out the names, types, shapes, and the
number of attributes assigned to each variable.

@cindex attributes
@findex ncattname
@findex NCANAM
@findex ncattinq
@findex NCAINQ
@findex ncattget
@findex NCAGT
@findex NCAGTC
Once the number of attributes for a variable is known, successive calls
to @code{ncattname} (or @code{NCANAM}) return the name for
each attribute given the netCDF ID, variable ID, and attribute number.
Armed with the attribute name, a call to @code{ncattinq} (or
@code{NCAINQ}) returns its type and length.  Given the type
and length, the generic application can allocate enough space to hold
the attribute values.  Then a call to @code{ncattget} (or @code{NCAGT}
or @code{NCAGTC}) returns the attribute values.

@findex ncvarget1
@findex NCVGT1
@findex NCVG1C
@findex ncvarget
@findex NCVGT
@findex NCVGTC
Once the names, IDs, types, shapes, and lengths of all netCDF components
are known, data values can be accessed by calling @code{ncvarget1} (or
@code{NCVGT1} or @code{NCVG1C}) for single values, or @code{ncvarget}
(or @code{NCVGT} or @code{NCVGTC}) for aggregates of values using
hyperslab access.

@node Adding Components, Error Handling, Reading with Unknown Names, Usage
@section Adding New Dimensions, Variables, Attributes

@cindex adding dimensions
@cindex adding variables
@cindex adding attributes
@cindex deleting attributes
@cindex renaming attributes
@cindex renaming dimensions
@cindex renaming variables
An existing netCDF file can be extensively altered.  New dimensions,
variables, and attributes can be added or existing ones renamed, and
existing attributes can be deleted.  Existing dimensions, variables, and
attributes can be renamed.  The following code template lists a typical
sequence of calls to add new netCDF components to an existing file:

@findex ncopen
@findex ncredef
@findex ncdimdef
@findex ncvardef
@findex ncattput
@findex ncendef
@findex ncvarput
@findex ncclose
@example
    ncopen           /* open existing netCDF */
      @dots{}
    ncredef          /* put it into define mode */
        @dots{}
      ncdimdef       /* define additional dimensions (if any) */
        @dots{}
      ncvardef       /* define additional variables (if any) */
        @dots{}
      ncattput       /* define additional attributes (if any) */
        @dots{}
    ncendef          /* check all definitions, leave define mode */
      @dots{}
    ncvarput         /* provide values for new variables */
      @dots{}
    ncclose          /* save netCDF file */
@end example

In FORTRAN, the corresponding sequence looks like this:
@findex NCOPN
@findex NCREDF
@findex NCDDEF
@findex NCVDEF
@findex NCAPT
@findex NCAPTC
@findex NCENDF
@findex NCVPT
@findex NCVPTC
@findex NCCLOS
@example
    CALL NCOPN             !  open existing netCDF 
      @dots{}
    CALL NCREDF            !  put it into define mode 
        @dots{}
      CALL NCDDEF          !  define additional dimensions (if any) 
        @dots{}
      CALL NCVDEF          !  define additional variables (if any) 
        @dots{}
      CALL NCAPT or NCAPTC !  define additional attributes (if any) 
        @dots{}
    CALL NCENDF            !  check all definitions, leave define mode 
      @dots{}
    CALL NCVPT or NCVPTC   !  provide values for new variables 
      @dots{}
    CALL NCCLOS            !  save netCDF file 
@end example

@cindex data mode
@cindex define mode
@findex ncopen
@findex NCOPN
@findex ncredef
@findex NCREDF
@findex ncdimdef
@findex NCDDEF
@findex ncvardef
@findex NCVDEF
@findex ncattput
@findex NCAPT
@findex NCAPTC
A netCDF file is first opened by the @code{ncopen} (or @code{NCOPN})
call.  This call puts you in @dfn{data mode}, which means existing data
values can be accessed and changed, existing attributes can be changed
(so long as they do not grow), but nothing can be added.  To add new
netCDF dimensions, variables, or attributes you must leave data mode and
enter @dfn{define mode}, by calling @code{ncredef} (or @code{NCREDF}).
In define mode, call @code{ncdimdef} (or @code{NCDDEF}) to define new
dimensions, @code{ncvardef} (or @code{NCVDEF}) to define new variables
(using the new dimensions), and @code{ncattput} (or @code{NCAPT} or
@code{NCAPTC}) to assign new attributes to variables or enlarge old
attributes.

@findex ncendef
@findex NCENDF
@findex ncclose
@findex NCCLOS
You can leave define mode and reenter data mode, checking
all the new definitions for consistency and committing the changes to
disk, by calling @code{ncendef} (or @code{NCENDF}).  If you do not wish
to reenter data mode, just call @code{ncclose} (or @code{NCCLOS}), which
will have the effect of first calling @code{ncendef} (or @code{NCENDF}).

@cindex aborting define mode
@cindex restoring old definitions
@findex ncendef
@findex NCENDF
@findex ncabort
@findex NCABOR
@findex ncclose
@findex NCCLOS
Until the @code{ncendef} (or @code{NCENDF}) call, you may back out of
all the redefinitions made in define mode and restore the previous state
of the netCDF by calling @code{ncabort} (or @code{NCABOR}).  You may
also use the @code{ncabort} call to restore the netCDF to a consistent
state if the call to @code{ncendef} (or @code{NCENDF}) fails.  If you
have called @code{ncclose} (or @code{NCCLOS}) from definition mode and
the implied call to @code{ncendef} (or @code{NCENDF}) fails,
@code{ncabort} (or @code{NCABOR}) will automatically be called to close
the netCDF in its previous consistent state (before you entered define
mode).

@node Error Handling, , Adding Components, Usage
@section Error Handling

@cindex error handling
@cindex error messages
@cindex suppressing error messages
@cindex error returns
@cindex default error handling
By default all netCDF library routines print an error message and exit
when an error has occurred.  If this error
behavior is acceptable, you never need to check error returns,
since any condition that would result in an error will print an
explanatory message and exit.  All the examples in this document assume
this default error-handling behavior, so the examples include no
checking of error returns.

@vindex ncopts
@vindex NC_VERBOSE
@vindex NC_FATAL
@cindex error options
@cindex fatal errors
@cindex error messages
In the C interface, errors may be handled more flexibly by setting the
external integer @code{ncopts}, declared in the file @file{netcdf.h}.
Two aspects of the error-handling behavior can be modified
independently: the suppression of error messages, and the fatality of
errors.  The default behavior is specified by the assignment
@example
ncopts = NC_VERBOSE | NC_FATAL;
@end example
@noindent
where @code{NC_VERBOSE} and @code{NC_FATAL} are predefined constants
from the include file @file{netcdf.h}.

@vindex ncerr
@vindex error returns
If you want error messages but do not wish errors to be fatal, turn off
the fatal error flag with:
@example
ncopts = NC_VERBOSE;
@end example
@noindent
If you want neither error messages nor fatal errors, turn off both flags
with:
@example
ncopts = 0;
@end example
@noindent
In either case, you should check the return value after each call to a
netCDF function.  The integer @code{-1} is returned whenever an error
occurs and @code{NC_FATAL} is off, so you can detect error returns and
handle the errors appropriately.  Another externally-defined integer,
@code{ncerr}, contains a netCDF-specific error code that can be used
after an error has occurred to determine what the nature of the error
was.  The names and descriptions of netCDF error codes are included in
the file @file{netcdf.h}.

@vindex NCPOPT
@vindex NCGOPT
@vindex NCVERBOS
@vindex NCFATAL
In the FORTRAN interface, the error options described above can
be accessed by using the routines NCPOPT and NCGOPT.  The default error-
handling behavior is equivalent to the statement
@example
      CALL NCPOPT(NCVERBOS+NCFATAL)
@end example
@noindent
where the values of NCVERBOS and NCFATAL are pre-defined constants from
the FORTRAN include file @file{netcdf.inc}.
@noindent
If you want error messages, but do not wish errors to be fatal, turn
off the fatal error flag with:
@example
      CALL NCPOPT(NCVERBOS)
@end example
@noindent
If you want neither error messages nor fatal errors, turn off both flags
with:
@example
      CALL NCPOPT(0)
@end example
@noindent
To get the current value of the error options, use
@example
      CALL NCGOPT(NCOPTS)
@end example

@vindex rcode
In either case, the integer return code (the last parameter in all of the
FORTRAN subroutines and functions) contains the non-zero netCDF-specific
error number that can be used to determine the nature of the error.  Names
and descriptions of netCDF error codes are included in the file
@file{netcdf.inc}.

@node File Operations, Dimensions, Usage, Top
@chapter netCDF Operations

This chapter presents the interfaces of the netCDF routines that deal
with a netCDF file as a whole.

@cindex netCDF file name
@cindex netCDF ID
@cindex netCDF handle
A netCDF file that has not yet been opened can only be referred to by
its file name.  Once a netCDF file is opened, it is referred to by an
ID, which is a small nonnegative integer returned when you create or
open the file.  A netCDF ID is a file @dfn{handle}, much like a file
descriptor in C or a logical unit number in FORTRAN.  In any single
program, the netCDF IDs of distinct open netCDFs are distinct.  A single
netCDF file may be opened multiple times and will then have multiple
distinct netCDF IDs; however at most one of the open instances of a
single netCDF file should permit writing.  When an open netCDF file is
closed, its ID no longer refers to it, and that ID may be subsequently
reassigned to refer to a different netCDF that is opened later.

@cindex netCDF operations
The operations supported on a netCDF as a single object are
@itemize @bullet

@item
Create, given file path and whether to overwrite or not.

@item
Open for access, given file path and read or write intent.

@item
Put into define mode, to add dimensions, variables, or attributes.

@item
Take out of define mode, checking consistency of additions.

@item
Close, writing to disk if required.

@item
Get number of dimensions, number of variables, number of global
attributes, and ID of the unlimited dimension if any.

@item
Synchronize to disk to make sure it is current.

@end itemize
@noindent
After a summary of conventions used in describing the netCDF C and
FORTRAN interfaces, the rest of this chapter presents the interfaces for
these operations.

@menu
* Interface Descriptions::   Conventions for netCDF library interface
                             descriptions.
* nccreate and NCCRE::       Create a netCDF file.
* ncopen and NCOPN::         Open a netCDF file for access.
* ncredef and NCREDF::       Put open netCDF file into define mode.
* ncendef and NCENDF::       Leave Define Mode.
* ncclose and NCCLOS::       Close an Open netCDF File.
* ncinquire and NCINQ::      Inquire about an Open netCDF File.
* ncsync and NCSNC::         Synchronize an Open netCDF File to Disk.
* ncabort and NCABOR::       Back Out of Recent Definitions.
@end menu

@node Interface Descriptions, nccreate and NCCRE, , File Operations
@section netCDF Library Interface Descriptions

@cindex interface descriptions
@cindex example conventions
@cindex conventions in examples
@cindex error conditions
@cindex examples
@cindex function prototypes

Each interface description for a particular netCDF function in this and
later chapters contains
@itemize @bullet

@item
a description of the purpose of the function,

@item
a list of possible error conditions,

@item
a C function prototype that presents the type and order of the formal
parameters to the function,

@item
a description of each formal parameter in the C interface

@item
an example of a C program fragment calling the netCDF function and
perhaps other netCDF functions to do something useful,

@item
a FORTRAN function prototype that presents the type and order of the
formal parameters to the FORTRAN function or functions that provide the
same functionality as the C function,

@item
a description of each formal parameter in the FORTRAN interface, and

@item
an example of a FORTRAN program fragment that duplicates the function of
the example C fragment.
@end itemize

The C function prototypes specify the order and type of each formal
parameter and conform to the ANSI C standard.  FORTRAN does not have
function prototypes, but a similar syntax is used to concisely present
the order and types of FORTRAN formal parameters.  In the few cases in
which a single C function corresponds to two FORTRAN functions, the
FORTRAN functions prototypes are presented together.

The FORTRAN examples use two nonstandard notations: @code{INCLUDE}
statements and in-line comments.  In each case, we use the VMS FORTRAN
notation, as in the following example:
@example
      INCLUDE 'netcdf.inc'
      INTEGER CDFID       ! this is an in-line comment
@end example
FORTRAN examples (and the FORTRAN interface) abide by the six-character
limitation on the length of FORTRAN names, except that
parameters names may be up to eight characters long.

@page
@node nccreate and NCCRE, ncopen and NCOPN, Interface Descriptions, File Operations
@section  Create a netCDF file

@cindex netCDF file creation
@cindex creating a netCDF file
@findex nccreate
@findex NCCRE
The function @code{nccreate} (or @code{NCCRE} for FORTRAN) creates a
new netCDF file, returning a netCDF ID that can subsequently be used to
refer to the netCDF file.  The new netCDF file is placed in define mode.

In case of an error, @code{nccreate} returns -1; @code{NCCRE} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@item
Passing a file name that includes a directory that does not exist.

@vindex NC_NOCLOBBER
@vindex NCNOCLOB
@item
Specifying a file name of a file that exists and also specifying
@code{NC_NOCLOBBER} (or @code{NCNOCLOB}).

@item
Attempting to create a netCDF file in a directory where you don't have
permission to create files.
@end itemize

@findex nccreate
@unnumberedsubsec nccreate:  C Interface
@example
int nccreate (char* path, int cmode);
@end example

@table @code

@item path
The file name of the new netCDF file.  This can be given as either an
absolute path name (from the root of the file system) or a relative
path name (from the current directory).

@vindex NC_CLOBBER
@vindex NC_NOCLOBBER
@item cmode
Should be specified as either @code{NC_CLOBBER} or @code{NC_NOCLOBBER}.  These
constants are defined in the include file @file{netcdf.h}.
@code{NC_CLOBBER} means that even if the file already exists, you want to
create a new file with the same name, erasing the old file's contents.
@code{NC_NOCLOBBER} means you want to create a new netCDF file only if the
given file name does not refer to a file that already exists.
@end table

@findex nccreate
@vindex NC_NOCLOBBER
Here is an example of the creation of a netCDF file named
@file{foo.cdf}; we want the file to be created in the current
directory only if it does not already exist:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid;
   @dots{}
cdfid = nccreate("foo.cdf", NC_NOCLOBBER);
@end group
@end example

@page				@c because texinfo didn't do it right
@unnumberedsubsec NCCRE:  FORTRAN Interface

@findex NCCRE
@example
INTEGER FUNCTION NCCRE (CHARACTER*(*) PATH, INTEGER CMODE,
                        INTEGER RCODE)
@end example

@table @code

@item PATH
The file name of the new netCDF file.  This can be given as either an
absolute path name (from the root of the file system) or a relative
path name (from the current directory).

@vindex NCCLOB
@vindex NCNOCLOB
@item CMODE
Should be specified as either @code{NCCLOB} or @code{NCNOCLOB}.  These
constants are defined in the include file @file{netcdf.inc}.
@code{NCCLOB} means that even if the file already exists, you want to
create a new file with the same name, erasing the old file's contents.
@code{NCNOCLOB} means you want to create a new netCDF file only if the
given file name does not refer to a file that already exists.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCCRE
Here is an example of the creation of a netCDF file named
@file{foo.cdf}, assuming we want the file to be created in the current
directory only if it does not already exist:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID
         @dots{}
      CDFID = NCCRE('foo.cdf', NCNOCLOB, RCODE)
@end group
@end example

@page
@node ncopen and NCOPN, ncredef and NCREDF, nccreate and NCCRE, File Operations
@section Open a netCDF File for Access

@cindex opening a netCDF file
@findex ncopen
@findex NCOPN
The function @code{ncopen} (or @code{NCOPN} for FORTRAN) 
opens an existing netCDF file for access.

In case of an error, @code{ncopen} returns -1; @code{NCOPN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@item
The specified netCDF file does not exist.

@vindex NC_WRITE
@vindex NC_NOWRITE
@item
The mode specified is something other than @code{NC_WRITE} or
@code{NC_NOWRITE}.
@end itemize

@findex ncopen
@unnumberedsubsec ncopen:  C Interface
@example
int ncopen(char* path,int mode);
@end example

@table @code

@item path
Absolute or relative file name for netCDF file to be opened.

@vindex NC_WRITE
@vindex NC_NOWRITE
@item mode
Either @code{NC_WRITE}, to open the file for writing, or @code{NC_NOWRITE}, to
open the file read-only.  ``Writing'' means any kind of change to the
file, including appending or changing data, adding or renaming dimensions,
variables, and attributes, or deleting attributes.
@end table

@findex ncopen
@vindex NC_NOWRITE
Here is an example using @code{ncopen} to open an existing netCDF file
named @file{foo.cdf} for reading:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid;
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
@end group
@end example

@findex NCOPN
@unnumberedsubsec NCOPN:  FORTRAN Interface
@example
      INTEGER FUNCTION NCOPN(CHARACTER*(*) PATH,
     +                       INTEGER RWMODE,
     +                       INTEGER RCODE)
@end example

@table @code

@item PATH
Absolute or relative file name for netCDF file to be opened.

@vindex NCWRITE
@vindex NCNOWRIT
@item RWMODE
Either @code{NCWRITE}, to open the file for writing, or @code{NCNOWRIT}, to
open the file read-only.  ``Writing'' means any kind of change to the
file, including appending or changing data, adding or renaming dimensions,
variables, and attributes, or deleting attributes.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
Here is an example of using @code{NCOPN} to open an existing netCDF file
named @file{foo.cdf} for reading:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID
         @dots{}
      CDFID = NCOPN('foo.cdf', NCNOWRIT, RCODE)
@end group
@end example

@page
@node ncredef and NCREDF, ncendef and NCENDF, ncopen and NCOPN, File Operations
@section Put Open netCDF File into Define Mode

@cindex define mode
@cindex adding dimensions
@cindex adding variables
@cindex adding attributes
@cindex renaming dimensions
@cindex renaming variables
@cindex renaming attributes
@cindex deleting attributes
@findex ncredef
@findex NCREDF
The function @code{ncredef} (or @code{NCREDF} for FORTRAN) 
puts an open netCDF file into define mode, so dimensions, variables,
and attributes can be added or renamed and attributes can be deleted.

In case of an error, @code{ncredef} returns -1; @code{NCREDF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@item
The specified netCDF file is already in define mode.

@item
The specified netCDF file was opened for read-only.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncredef
@unnumberedsubsec ncredef:  C Interface
@example
int ncredef(int cdfid);
@end example

@table @code

@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex ncopen
@findex ncredef
@vindex NC_NOWRITE
Here is an example using @code{ncredef} to open an existing netCDF file
named @file{foo.cdf} and put it into define mode:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid;
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);    /* open file */
   @dots{}
ncredef(cdfid);                        /* put in define mode */
@end group
@end example

@findex NCREDF
@unnumberedsubsec NCREDF:  FORTRAN Interface
@example
SUBROUTINE NCREDF(INTEGER CDFID, INTEGER RCODE)
@end example

@table @code

@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCREDF
@vindex NCNOWRIT
Here is an example of using @code{NCREDF} to open an existing netCDF file
named @file{foo.cdf} and put it into define mode:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID
         @dots{}
      CDFID = NCOPN('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      CALL NCREDF(CDFID, RCODE)
@end group
@end example

@page
@node ncendef and NCENDF, ncclose and NCCLOS, ncredef and NCREDF, File Operations
@section Leave Define Mode

@cindex define mode
@cindex data mode
@findex ncendef
@findex NCENDF
The function @code{ncendef} (or @code{NCENDF} for FORTRAN) takes an open
netCDF file out of define mode.  The changes made to the netCDF file
while it was in define mode are checked and committed to disk if no
problems occurred.  The netCDF file is then placed in data mode, so
variable data can be read or written.

In case of an error, @code{ncendef} returns -1; @code{NCENDF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@item
The specified netCDF file is not in define mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncendef
@unnumberedsubsec ncendef:  C Interface
@example
int ncendef(int cdfid);
@end example

@table @code

@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table
@findex nccreate
@findex ncendef
@vindex NC_NOCLOBBER
Here is an example using @code{ncendef} to finish the definitions of a
new netCDF file named @file{foo.cdf} and put it into data mode:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid;
   @dots{}
cdfid = nccreate("foo.cdf", NC_NOCLOBBER);

   @dots{}      /* create dimensions, variables, attributes */

ncendef(cdfid);                        /* leave define mode */
@end group
@end example

@findex NCENDF
@unnumberedsubsec NCENDF:  FORTRAN Interface
@example
SUBROUTINE NCENDF(INTEGER CDFID, INTEGER RCODE)
@end example

@table @code

@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCENDF
@findex NCCRE
@vindex NCNOCLOB
Here is an example using @code{NCENDF} to finish the definitions of a
new netCDF file named @file{foo.cdf} and put it into data mode:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID
         @dots{}
      CDFID = NCCRE('foo.cdf', NCNOCLOB, RCODE)

         @dots{}  ! create dimensions, variables, attributes

      CALL NCENDF(CDFID, RCODE)
@end group
@end example

@page
@node ncclose and NCCLOS, ncinquire and NCINQ, ncendef and NCENDF, File Operations
@section Close an Open netCDF File

@cindex closing a netCDF file
@findex ncclose
@findex NCCLOS
@findex ncendef
@findex NCENDF
@findex ncabort
@findex NCABOR
@cindex netCDF ID
The function @code{ncclose} (or @code{NCCLOS} for FORTRAN) closes an
open netCDF file.  If the file is in define mode, @code{ncendef} (or
@code{NCENDF}) will be called before closing.  (In this case, if
@code{ncendef} (or @code{NCENDF}) returns an error, @code{ncabort} (or
@code{NCABOR}) will automatically be called to restore the file to the
consistent state before define mode was last entered.)  After an open
netCDF file is closed, its netCDF ID will be reassigned to the next
netCDF file that is opened or created.

In case of an error, @code{ncclose} returns -1; @code{NCCLOS} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@findex ncendef
@findex NCENDF
@item
The netCDF was in define mode and the automatic call made to
@code{ncendef} (or @code{NCENDF}) failed.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncclose
@unnumberedsubsec ncclose:  C Interface
@example
int ncclose(int cdfid);
@end example

@table @code

@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex nccreate
@findex ncclose
@vindex NC_NOCLOBBER
Here is an example using @code{ncclose} to finish the definitions of a
new netCDF file named @file{foo.cdf} and release its netCDF ID:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid;
   @dots{}
cdfid = nccreate("foo.cdf", NC_NOCLOBBER);

   @dots{}      /* create dimensions, variables, attributes */

ncclose(cdfid);                        /* close netCDF file */
@end group
@end example

@page				@c because texinfo didn't do it right
@unnumberedsubsec NCCLOS:  FORTRAN Interface

@findex NCCLOS
@example
SUBROUTINE NCCLOS(INTEGER CDFID, INTEGER RCODE)
@end example

@table @code

@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCCLOS
@findex NCCRE
@vindex NCNOCLOB
Here is an example using @code{NCCLOS} to finish the definitions of a
new netCDF file named @file{foo.cdf} and release its netCDF ID:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, RCODE
         @dots{}
      CDFID = NCCRE('foo.cdf', NCNOCLOB, RCODE)

         @dots{}  ! create dimensions, variables, attributes

      CALL NCCLOS(CDFID, RCODE)
@end group
@end example

@page
@node ncinquire and NCINQ, ncsync and NCSNC, ncclose and NCCLOS, File Operations
@section Inquire about an Open netCDF File

@cindex inquire about a netCDF file
@findex ncinquire
@findex NCINQ
The function @code{ncinquire} (@code{NCINQ} for FORTRAN) returns
information about an open netCDF file, given its netCDF ID.  It can be
called from either define mode or data mode.  It returns values for the
number of dimensions, the number of variables, the number of global
attributes, and the variable ID of the dimension defined with
unlimited size, if any.

In case of an error, @code{ncinquire} returns -1; @code{NCINQ} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncinquire
@unnumberedsubsec ncinquire:  C Interface
@example
int ncinquire(int cdfid, int* ndims, int* nvars, int* ngatts,
              int* recdim);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex number of dimensions
@item ndims
Returned number of dimensions defined for this netCDF file.

@cindex number of variables
@item nvars
Returned number of variables defined for this netCDF file.

@cindex number of global attributes
@cindex global attributes
@item ngatts
Returned number of global attributes defined for this netCDF file.

@cindex unlimited dimension ID
@item recdim
Returned ID of the unlimited dimension, if there is one for this netCDF
file.  If no unlimited size dimension has been defined, -1 is returned
for the value of @code{recdim}.
@end table

@findex ncopen
@findex ncinquire
@vindex NC_NOWRITE
Here is an example using @code{ncinquire} to find out about a netCDF
file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid, ndims, nvars, ngatts, recdim;
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
ncinquire(cdfid, &ndims, &nvars, &ngatts, &recdim);
@end group
@end example

@page				@c because texinfo didn't do it right
@unnumberedsubsec NCINQ:  FORTRAN Interface

@findex NCINQ
@example
      SUBROUTINE NCINQ(INTEGER CDFID, INTEGER NDIMS, INTEGER NVARS,
     *                 INTEGER NGATTS, INTEGER RECDIM, INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item NDIMS
Returned number of dimensions defined for this netCDF file.

@item NVARS
Returned number of variables defined for this netCDF file.

@item NGATTS
Returned number of global attributes defined for this netCDF file.

@cindex unlimited dimension ID
@item RECDIM
Returned ID of the unlimited dimension, if there is one for this netCDF
file.  If no unlimited size dimension has been defined, -1 is returned
for the value of @code{RECDIM}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCINQ
@vindex NCNOWRIT
Here is an example using @code{NCINQ} to find out about a netCDF
file named @file{foo.cdf}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, NDIMS, NVARS, NATTS, RECDIM, RCODE
         @dots{}
      CDFID = NCOPN('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      CALL NCINQ(CDFID, NDIMS, NVARS, NATTS, RECDIM, RCODE)
@end group
@end example

@page
@node ncsync and NCSNC, ncabort and NCABOR, ncinquire and NCINQ, File Operations
@section Synchronize an Open netCDF File to Disk

@cindex synchronize a netCDF file
@cindex data mode
@cindex define mode
@cindex performance
@cindex efficiency
@findex ncsync
@findex NCSNC
@findex ncendef
@findex NCENDF
The function @code{ncsync} (or @code{NCSNC} for FORTRAN) makes sure that
the disk copy of a netCDF file open for writing is current.  The netCDF
file must be in data mode.  A netCDF file in define mode is synchronized
to disk only when @code{ncendef} (or @code{NCENDF}) is called.  It can
be expensive in computer resources to always synchronize to disk after
every write of variable data or change of an attribute value.  There are two
reasons you might want to synchronize after writes:
@itemize @bullet
@item
to minimize data loss in case of abnormal termination, or

@cindex shared access
@item
to make data available to other processes for reading immediately after it
is written.
@end itemize

@cindex closing a netCDF file
@cindex define mode
@cindex data mode
Data is automatically synchronized to disk when a netCDF file is closed,
or whenever you leave define mode.

In case of an error, @code{ncsync} returns -1; @code{NCSNC} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@item
The netCDF file is in define mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncsync
@unnumberedsubsec ncsync:  C Interface
@example
int ncsync(int cdfid);
@end example

@table @code

@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex ncsync
@findex ncopen
@vindex NC_WRITE
Here is an example using @code{ncsync} to synchronize the disk writes of
a netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid;
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);  /* open for writing */

   @dots{}          /* write data or change attributes */

ncsync(cdfid);      /* synchronize to disk */
@end group
@end example

@findex NCSNC
@unnumberedsubsec NCSNC:  FORTRAN Interface
@example
      SUBROUTINE NCSNC(INTEGER CDFID, INTEGER RCODE)
@end example

@table @code

@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCSNC
@findex NCOPN
@vindex NCNOWRIT
Here is an example using @code{NCSNC} to synchronize the disk writes of
a netCDF file named @file{foo.cdf}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, RCODE
         @dots{}
      CDFID = NCOPN('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
* write data or change attributes
         @dots{}
      CALL NCSNC(CDFID, RCODE)
@end group
@end example

@page
@node ncabort and NCABOR, , ncsync and NCSNC, File Operations
@section Back Out of Recent Definitions

@cindex canceling definitions
@cindex backing out of definitions
@cindex aborting definitions
@findex ncabort
@findex NCABOR
@cindex define mode
@cindex data mode
@cindex closing a netCDF file
@cindex creating a netCDF file
@cindex deleting a netCDF file
@findex ncredef
@findex NCREDF
The function @code{ncabort} (or @code{NCABOR} for FORTRAN), if not in
define mode, closes the netCDF file.  If the file is being created and
is still in define mode, the file is deleted.  If define mode was
entered by a call to @code{ncredef} (or @code{NCREDF}), the netCDF file
is restored to its state before definition mode was entered and the file
is closed.  The main reason for calling @code{ncabort} (or
@code{NCABOR}) is to restore the netCDF to a known consistent state in
case anything goes wrong during the definition of new dimensions,
variables, or attributes.

@findex ncclose
@findex NCCLOS
This function is called automatically if @code{ncclose} (or
@code{NCCLOS}) is called from define mode and the call to leave define
mode before closing fails.

In case of an error, @code{ncabort} returns -1; @code{NCABOR} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@item
When called from define mode while creating a netCDF, deletion of the
file failed.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncabort
@unnumberedsubsec ncabort:  C Interface
@example
int ncabort(int cdfid);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex ncdimdef
@findex ncopen
@vindex NC_WRITE
@findex ncredef
@findex ncabort
Here is an example using @code{ncabort} to back out of redefinitions of
a file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid;
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);  /* open for writing */
   @dots{}
ncredef(cdfid);                    /* enter define mode */
   @dots{}
if (ncdimdef(cdfid, "lat", 18) == -1)
   ncabort(cdfid);                 /* define failed, abort */
@end group
@end example

@page				@c because texinfo didn't do it right
@unnumberedsubsec NCABOR:  FORTRAN Interface

@findex NCABOR
@example
      SUBROUTINE NCABOR(INTEGER CDFID, INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@vindex NCWRITE
@findex NCREDF
@findex NCDDEF
@findex NCABOR
Here is an example using @code{NCABOR} to back out of redefinitions of
a file named @file{foo.cdf}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, RCODE, LATID
         @dots{}
      CDFID = NCOPN('foo.cdf', NCWRITE, RCODE)
         @dots{}
      CALL NCREDF(CDFID, RCODE)
         @dots{}
      LATID = NCDDEF(CDFID, 'LAT', 18, RCODE)
      IF (RCODE .EQ. -1) THEN  ! dimension definition failed
         CALL NCABOR(CDFID, RCODE)  ! abort redefinitions
      ENDIF
         @dots{}
@end group
@end example

@node Dimensions, Variables, File Operations, Top
@chapter Dimensions

@cindex dimensions
@cindex define mode
@cindex unlimited dimension
@cindex record dimension
@cindex records
@cindex dimension ID
Dimensions for a netCDF file are defined when it is created, while the
netCDF file is in define mode.  Additional dimensions may be added
later by reentering define mode.  A netCDF dimension has a name and a
size.  At most one dimension in a netCDF can
have the @code{NC_UNLIMITED} size, which means a variable using this
dimension can grow to any length (like a record number in a file).

@cindex maximum number of dimensions
@cindex MAX_NC_DIMS
@cindex generic applications
@cindex netCDF implementation
There is a suggested limit (currently 32) to the number of dimensions
that can be defined in a single netCDF file.  The limit is the value of
the predefined macro @code{MAX_NC_DIMS} (MAXNCDIM for FORTRAN).  The
purpose of the limit is to make writing generic applications simpler, so
that generic applications need only provide an array of
@code{MAX_NC_DIMS} dimensions to handle any netCDF file.  The
implementation of the netCDF library does not enforce this advisory
maximium, so it is possible to use more dimensions if necessary; just
don't expect generic applications or netCDF utilities to be able to
handle the resulting netCDF files.

@cindex dimension name
@cindex dimension size
Ordinarily, the name and size of a dimension are fixed when the
dimension is first defined.  The name may be changed later, but the size
of a dimension cannot be changed without copying the netCDF to a new
netCDF with a redefined dimension size.

Operations supported on dimensions are
@itemize @bullet
@item
create a dimension, given its name and size
@item
get a dimension ID from its name
@item
get a dimension's name and size from its ID
@item
rename a dimension
@end itemize

@menu
* ncdimdef and NCDDEF::    Create a Dimension
* ncdimid and NCDID::      Get a Dimension ID from Its Name
* ncdiminq and NCDINQ::    Inquire about a Dimension
* ncdimrename and NCDREN:: Rename a Dimension
@end menu

@page
@node ncdimdef and NCDDEF, ncdimid and NCDID,  , Dimensions
@section Create a Dimension

@cindex creating a dimension
@cindex dimension IDs
@cindex dimension names
@cindex dimension size
@cindex unlimited dimension
@cindex record dimension
@findex ncdimdef
@findex NCDDEF
The function @code{ncdimdef} (or @code{NCDDEF} for FORTRAN) adds a new
dimension to an open netCDF file in define mode.  It returns a dimension
ID, given the netCDF ID, the dimension name, and the dimension size.  At
most one unlimited size dimension, called the record dimension,
may be defined for each netCDF file.

In case of an error, @code{ncdimdef} returns -1; @code{NCDDEF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The netCDF file is not in definition mode.

@item
The specified dimension name is the name of another existing dimension.

@item
The specified size is not greater than zero.

@item
The specified size is unlimited, but there is already an
unlimited size dimension defined for this netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdimdef
@unnumberedsubsec ncdimdef:  C Interface
@example
int ncdimdef(int cdfid, char* name, int size);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Dimension name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore
(@code{_}).  Case is significant.

@vindex NC_UNLIMITED
@item size
Size of dimension, that is, number of values for this dimension as an
index to variables that use it.  This should be either a positive
integer or the predefined constant @code{NC_UNLIMITED}.
@end table

@findex ncdimdef
@findex nccreate
@vindex NC_UNLIMITED
@vindex NC_NOCLOBBER
Here is an example using @code{ncdimdef} to create a dimension named
@code{lat} of size 18 and a record dimension named @code{rec} in a new
netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid, latid, recid;
   @dots{}
cdfid = nccreate("foo.cdf", NC_NOCLOBBER);
   @dots{}
latid = ncdimdef(cdfid, "lat", 18);
recid = ncdimdef(cdfid, "rec", NC_UNLIMITED);
@end group
@end example

@findex NCDDEF
@unnumberedsubsec NCDDEF:  FORTRAN Interface
@example
      SUBROUTINE NCDDEF (INTEGER CDFID,
     +                   CHARACTER*(*) DIMNAM,
     +                   INTEGER DIMSIZ,
     +                   INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMNAM
Dimension name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore (@code{_}).  Case is
significant.

@vindex NCUNLIM
@item DIMSIZ
Size of dimension, that is, number of values for this dimension as an
index to variables that use it.  This should be either a positive
integer or the predefined constant @code{NCUNLIM}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDDEF
@findex NCCRE
@vindex NCNOCLOB
@vindex NCUNLIM
Here is an example using @code{NCDDEF} to create a dimension named
@code{lat} of size 18 and a record dimension named @code{rec} in a new
netCDF file named @file{foo.cdf}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, RCODE, LATID, RECID
         @dots{}
      CDFID = NCCRE('foo.cdf', NCNOCLOB, RCODE)
         @dots{}
      LATID = NCDDEF(CDFID, 'lat', 18, RCODE)
      RECID = NCDDEF(CDFID, 'rec', NCUNLIM, RCODE)
@end group
@end example

@page
@node ncdimid and NCDID, ncdiminq and NCDINQ, ncdimdef and NCDDEF, Dimensions
@section Get a Dimension ID from Its Name
@cindex getting dimension ID
@cindex dimension IDs
@cindex dimension names
@findex ncdimid
@findex NCDID
The function @code{ncdimid} (or @code{NCDID} for FORTRAN) returns the ID
of a netCDF dimension, given the name of the dimension.  If @code{ndims}
is the number of dimensions defined for a netCDF file, each dimension
has an ID between @code{0} and @code{ndims-1} (or @code{1} and
@code{ndims} for FORTRAN).

In case of an error, @code{ncdimid} returns -1; @code{NCDID} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet

@item
The name that was specified is not the name of any currently defined
dimension in the netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdimid
@unnumberedsubsec ncdimid:  C Interface
@example
int ncdimid(int cdfid, char* name);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Dimension name, a character string beginning with a letter and followed
by any sequence of letters, digits, or underscore (@code{_}) characters.
Case is significant in dimension names.
@end table

@findex ncdimid
@findex ncopen
@vindex NC_NOWRITE
Here is an example using @code{ncdimid} to determine the dimension ID of
a dimension named @code{lat}, assumed to have been defined previously in
an existing netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid, latid;
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);  /* open for reading */
   @dots{}
latid = ncdimid(cdfid, "lat");
@end group
@end example

@page				@c because texinfo didn't do it right
@unnumberedsubsec NCDID:  FORTRAN Interface

@findex NCDID
@example
      INTEGER FUNCTION NCDID (INTEGER CDFID,
     +                        CHARACTER*(*) DIMNAME,
     +                        INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMNAME
Dimension name, a character string beginning with a letter and followed
by any sequence of letters, digits, or underscore (@code{_}) characters.
Case is significant in dimension names.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDID
@findex NCOPN
@vindex NCNOWRIT
Here is an example using @code{NCDID} to determine the dimension ID of
a dimension named @code{lat}, assumed to have been defined previously in
an existing netCDF file named @file{foo.cdf}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, RCODE, LATID
         @dots{}
      CDFID = NCOPN('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      LATID = NCDID(CDFID, 'lat', RCODE)
@end group
@end example

@page
@node ncdiminq and NCDINQ, ncdimrename and NCDREN, ncdimid and NCDID, Dimensions
@section Inquire about a Dimension

@cindex getting dimension name
@cindex getting dimension size
@cindex dimension IDs
@cindex dimension names
@cindex dimension size
@cindex dimension inquire
@cindex maximum number of records
@cindex number of records written
@cindex records
@cindex unlimited dimension
@cindex record dimension
@findex ncdiminq
@findex NCDINQ
The function @code{ncdiminq} (or @code{NCDINQ} for FORTRAN) returns the
name and size of a dimension, given its ID.  The size for the
unlimited dimension, if any, is the maximum value used so far in
writing data for that dimension (which is the same as the current
maximum record number).

In case of an error, @code{ncdiminq} returns -1; @code{NCDINQ} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The dimension ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdiminq
@unnumberedsubsec ncdiminq:  C Interface
@example
int ncdiminq(int cdfid, int dimid, char* name, int* size);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item dimid
Dimension ID, as returned from a previous call to @code{ncdimid} or
@code{ncdimdef}.

@cindex dimension names
@vindex MAX_NC_NAME
@item name
Returned dimension name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
dimension name is given by the predefined constant @code{MAX_NC_NAME}.
If the name parameter is given as @samp{(char *) 0}, no name will be
returned so no space needs to be allocated.

@item size
Returned size of dimension.  For the unlimited dimension, this is the
current maximum value used for writing any variables with this
dimension, that is the maximum record number.
@end table

@findex ncdiminq
@findex ncopen
@findex ncinquire
@vindex NC_NOWRITE
@findex ncdimid
@vindex MAX_NC_NAME
Here is an example using @code{ncdiminq} to determine the size of a
dimension named @code{lat}, and the name and current maximum size of the
unlimited (or record) dimension for an existing netCDF file named
@file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid, latid, latsize, ndims, nvars, ngatts, recid;
char recname[MAX_NC_NAME];
int recs;
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);  /* open for reading */
   @dots{}
latid = ncdimid(cdfid, "lat");
/* get lat size, but don't get name, since we already know it */
ncdiminq(cdfid, latid, (char *) 0, &latsize);
/* get ID of record dimension (among other things) */
ncinquire(cdfid, &ndims, &nvars, &ngatts, &recid);
/* get record dimension name and current size */
ncdiminq(cdfid, recid, recname, &recs);
@end group
@end example

@findex NCDINQ
@unnumberedsubsec NCDINQ:  FORTRAN Interface
@example
      SUBROUTINE NCDINQ (INTEGER CDFID, INTEGER DIMID,
     +                   CHARACTER*(*) DIMNAM, INTEGER DIMSIZ,
     +                   INTEGER RCODE)
@end example

@table @code

@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMID
Dimension ID, as returned from a previous call to @code{NCDID} or @code{NCDDEF}.

@cindex dimension names
@vindex MAXNCNAM
@item DIMNAM
Returned dimension name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
dimension name is given by the predefined constant @code{MAXNCNAM}.

@item DIMSIZ
Returned size of dimension.  For the unlimited dimension, this is
the current maximum value used for writing any variables with this
dimension, that is the maximum record number.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDINQ
@findex NCOPN
@findex NCINQ
@vindex NCNOWRIT
@findex NCDID
@vindex MAXNCNAM
Here is an example using @code{NCDINQ} to determine the size of a
dimension named @code{lat}, and the name and current maximum size of the
unlimited (or record) dimension for an existing netCDF file named
@file{foo.cdf}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, RCODE, LATID, LATSIZ
      INTEGER NDIMS, NVARS, NGATTS, RECID, NRECS
* 31 in following statement is parameter MAXNCNAM
      CHARACTER*31 LATNAM, RECNAM
         @dots{}
      CDFID = NCOPN('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      LATID = NCDID(CDFID, 'lat', RCODE)
* get lat name and size, (even though we already know name)
      CALL NCDINQ(CDFID, LATID, LATNAM, LATSIZ, RCODE)
* get ID of record dimension (among other things)
      CALL NCINQ(CDFID, NDIMS, NVARS, NGATTS, RECID)
* get record dimension name and current size
      CALL NCDINQ(CDFID, RECID, RECNAME, NRECS)
@end group
@end example

@page
@node ncdimrename and NCDREN,  , ncdiminq and NCDINQ, Dimensions
@section Rename a Dimension

@cindex renaming dimensions
@cindex dimension names
@findex ncdimrename
@findex NCDREN
The function @code{ncdimrename} (or @code{NCDREN} for FORTRAN) renames
an existing dimension in a netCDF open for writing.  If the new name is
longer than the old name, the netCDF must be in define mode.  You cannot
rename a dimension to have the same name as another dimension.

In case of an error, @code{ncdimrename} returns -1; @code{NCDREN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The new name is the name of another dimension.

@item
The dimension ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdimrename
@unnumberedsubsec ncdimrename:  C Interface
@example
int ncdimrename(int cdfid, int dimid, char* name);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item dimid
Dimension ID, as returned from a previous call to @code{ncdimid} or @code{ncdimdef}.

@item name
New dimension name.
@end table

@findex ncdimrename
@findex ncopen
@findex ncredef
@findex ncendef
@vindex NC_WRITE
@findex ncdimid
Here is an example using @code{ncdimrename} to rename the dimension
@code{lat} to @code{latitude} in an existing netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int cdfid, latid;
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);  /* open for writing */
   @dots{}
ncredef(cdfid);  /* put in define mode to rename dimension */
latid = ncdimid(cdfid, "lat");
ncdimrename(cdfid, latid, "latitude");
ncendef(cdfid);  /* leave define mode */
@end group
@end example

@page				@c because texinfo didn't do it right
@findex NCDREN
@unnumberedsubsec NCDREN:  FORTRAN Interface
@example
      SUBROUTINE NCDREN (INTEGER CDFID, INTEGER DIMID,
     +                   CHARACTER*(*) DIMNAME, INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMID
Dimension ID, as returned from a previous call to @code{NCDID} or
@code{NCDDEF}.

@item DIMNAM
New name for the dimension.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDREN
@findex NCREDF
@findex NCOPN
@vindex NCWRITE
@findex NCDID
@findex NCENDF
Here is an example using @code{NCDREN} to rename the dimension
"lat" to "latitude" in an existing netCDF file named @file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER CDFID, RCODE, LATID
         @dots{}
      CDFID = NCOPN('foo.cdf', NCWRITE, RCODE)
         @dots{}
* put in define mode to rename dimension
      CALL NCREDF(CDFID)
      LATID = NCDID(CDFID, 'lat', RCODE)
      CALL NCDREN(CDFID, LATID, 'latitude', RCODE)
* leave define mode
      CALL NCENDF(CDFID)
@end group
@end example

@node Variables, Attributes, Dimensions, Top
@chapter Variables

@cindex variables
@cindex define mode
@cindex variable name
@cindex variable type
@cindex variable shape
@cindex variable values
Variables for a netCDF file are defined when it is created, while the
netCDF file is in define mode.  Additional variables may be added later
by reentering define mode.  A netCDF variable has a name, a type, and a
shape, which are specified when it is defined.  A variable may also have
values, which are established later, in data mode.

@cindex unlimited dimension
@cindex record dimension
Ordinarily, the name, type, and shape are fixed when the variable is
first defined.  The name may be changed, but the type and shape of a
variable cannot be changed.  However, a variable defined in terms of
the unlimited dimension can grow without bound in that dimension.

@cindex variable ID
A netCDF variable is referred to by a small integer called a variable
ID.  Attributes may be associated with a variable to specify such
properties as units, special values, maximum and minimum valid values,
scaling factors, and offsets.

Operations supported on variables are
@itemize @bullet
@item
Create a variable, given its name, data type, and shape.

@item
Get a variable ID from its name.

@item
Get a variable's name, data type, shape, and number of attributes from its ID.

@item
Put a data value into a variable, given variable ID, indices, and value.

@item
Put a hyperslab of values into a variable, given variable ID, corner
indices, edge lengths, and a block of values.

@item
Get a data value from a variable, given variable ID and indices.

@item
Get a hyperslab of values from a variable, given variable ID, corner
indices, and edge lengths.

@item
Rename a variable.
@end itemize

@menu
* ncvardef and NCVDEF::     Create a Variable
* ncvarid and NCVID::       Get a Variable ID from Its Name
* ncvarinq and NCVINQ::     Get Information about a Variable from Its ID
* ncvarput1 and NCVPT1::    Write a Single Data Value
* ncvarput and NCVPT::      Write a Hyperslab of Values
* ncvarget1 and NCVGT1::    Read a Single Data Value
* ncvarget and NCVGT(C)::   Read a Hyperslab of Values
* Character String I/O::    Reading and Writing Character String Values
* Missing Values::          Conventions for Missing Values
* ncvarrename and NCVREN::  Rename a Variable
@end menu

@page
@node ncvardef and NCVDEF, ncvarid and NCVID,  , Variables
@section Create a Variable

@cindex creating a variable
@cindex variable ID
@cindex variable name
@cindex variable type
@cindex variable shape
@findex ncvardef
@findex NCVDEF
The function @code{ncvardef} (or @code{NCVDEF} for FORTRAN) adds a new
variable to an open netCDF file in define mode.  It returns a variable
ID, given the netCDF ID, the variable name, the variable type, the
number of dimensions, and a list of the dimension IDs.

@cindex define mode
@cindex maximum dimensions
@cindex dimension IDs
In case of an error, @code{ncvardef} returns -1; @code{NCVDEF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The netCDF file is not in define mode.

@item
The specified variable name is the name of another existing variable.

@item
The specified type is not a valid netCDF type.

@cindex maximum variable dimensions
@vindex MAX_VAR_DIMS
@item
The specified number of dimensions is negative or more than the
constant @code{MAX_VAR_DIMS}, the maximum number of dimensions
permitted for a netCDF variable.

@item
One or more of the dimension IDS in the list of dimensions is not a
valid dimension ID for the netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvardef
@unnumberedsubsec ncvardef:  C Interface
@example
int ncvardef(int cdfid, char* name, nc_type datatype,
             int ndims, int dim[]);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Variable name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore (@code{_}).  Case is
significant.

@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@item datatype
One of the set of predefined netCDF data types.  The type of this
parameter, @code{nc_type}, is defined in the netCDF header file.  The
valid netCDF data types are @code{NC_BYTE}, @code{NC_CHAR},
@code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE}.

@cindex maximum variable dimensions
@vindex MAX_VAR_DIMS
@item ndims
Number of dimensions for the variable.  For example, @code{2} specifies
a matrix, @code{1} specifies a vector, and @code{0} means the variable
is a scalar with no dimensions.  Must not be negative or greater than
the predefined constant @code{MAX_VAR_DIMS}.

@item dim
Vector of @code{ndims} dimension IDs corresponding to the variable
dimensions.  If the ID of the unlimited dimension is included, it
must be first.
@end table

@findex nccreate
@findex ncdimdef
@findex ncvardef
@vindex NC_UNLIMITED
@vindex NC_CLOBBER
Here is an example using @code{ncvardef} to create a variable named
@code{rh} of type @code{long} with three dimensions, @code{time},
@code{lat}, and @code{lon} in a new netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                        /* netCDF ID */
int  lat_dim, lon_dim, time_dim;   /* dimension IDs */
int  rh_id;                        /* variable ID */
int  rh_dims[3];                   /* variable shape */
   @dots{}
cdfid = nccreate("foo.cdf", NC_CLOBBER);
   @dots{}
                                   /* define dimensions */
lat_dim = ncdimdef(cdfid, "lat", 5);
lon_dim = ncdimdef(cdfid, "lon", 10);
time_dim = ncdimdef(cdfid, "time", NC_UNLIMITED);
   @dots{}
                                  /* define variable */
rh_dims[0] = time_dim;
rh_dims[1] = lat_dim;
rh_dims[2] = lon_dim;
rh_id = ncvardef (cdfid, "rh", NC_DOUBLE, 3, rh_dims);
@end group
@end example

@findex NCVDEF
@unnumberedsubsec NCVDEF:  FORTRAN Interface
@example
      INTEGER FUNCTION NCVDEF(INTEGER CDFID, CHARACTER*(*) VARNAM,
     +                        INTEGER VARTYP, INTEGER NVDIMS,
     +                        INTEGER VDIMS(*), INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARNAM
Variable name.  Must begin with an alphabetic character, which is
followed by zero or more alphanumeric characters including the underscore (@code{_}).
Case is significant.

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VARTYP
One of the set of predefined netCDF data types.  The valid netCDF data
types are @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE}.

@cindex maximum variable dimensions
@vindex MAXVDIMS
@item NVDIMS
Number of dimensions for the variable.  For example, @code{2} specifies
a matrix, @code{1} specifies a vector, and @code{0} means the variable
is a scalar with no dimensions.  Must not be negative or greater than
the predefined constant @code{MAXVDIMS}.

@item VDIMS
Vector of @code{NVDIMS} dimension IDs corresponding to the variable
dimensions.  If the ID of the unlimited dimension is included, it
must be last.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCCRE
@findex NCDDEF
@findex NCVDEF
@vindex NC_CLOBBER
@vindex NCUNLIM
Here is an example using @code{NCVDEF} to create a variable named
@code{rh} of type @code{long} with three dimensions, @code{time},
@code{lat}, and @code{lon} in a new netCDF file named @file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  LATDIM, LONDIM, TIMDIM ! dimension IDs
      INTEGER  RHID                    ! variable ID
      INTEGER  RHDIMS(3)               ! variable shape
         @dots{}
      CDFID = NCCRE ('foo.cdf', NC_CLOBBER, RCODE)
         @dots{}
                                       ! define dimensions
      LATDIM = NCDDEF(CDFID, 'lat', 5, RCODE)
      LONDIM = NCDDEF(CDFID, 'lon', 10, RCODE)
      TIMDIM = NCDDEF(CDFID, 'time', NCUNLIM, RCODE)
         @dots{}
                                       ! define variable
      RHDIMS(1) = TIMDIM
      RHDIMS(2) = LATDIM
      RHDIMS(3) = LONDIM
      RHID = NCVDEF (CDFID, 'rh', NCDOUBLE, 3, RHDIMS, RCODE)
@end group
@end example


@page
@node ncvarid and NCVID, ncvarinq and NCVINQ, ncvardef and NCVDEF, Variables
@section Get a Variable ID from Its Name

@cindex variable ID
@cindex variable name
@findex ncvarid
@findex NCVID
The function @code{ncvarid} (or @code{NCVID} for FORTRAN) returns the ID
of a netCDF variable, given its name.

In case of an error, @code{ncvarid} returns -1; @code{NCVID} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The specified variable name is not a valid name for a variable in the
specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarid
@unnumberedsubsec ncvarid:  C Interface
@example
int ncvarid(int cdfid, char* name);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Variable name for which ID is desired.
@end table

@findex ncopen
@findex ncvarid
@vindex NC_NOWRITE
Here is an example using @code{ncvarid} to find out the ID of a variable
named @code{rh} in an existing netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
@end group
@end example

@findex NCVID
@unnumberedsubsec NCVID:  FORTRAN Interface
@example
      INTEGER FUNCTION NCVID(INTEGER CDFID,
     +                       CHARACTER*(*) VARNAM,
     +                       INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARNAM
Variable name for which ID is desired.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@vindex NCNOWRIT
Here is an example using @code{NCVID} to find out the ID of a variable
named @code{rh} in an existing netCDF file named @file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  RHID                    ! variable ID
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)
@end group
@end example

@page
@node ncvarinq and NCVINQ, ncvarput1 and NCVPT1, ncvarid and NCVID, Variables
@section Get Information about a Variable from Its ID

@cindex getting variable name
@cindex getting variable type
@cindex getting variable shape
@cindex variable name
@cindex variable type
@cindex variable shape
@cindex variable inquire
@cindex variable dimensions
@findex ncvarinq
@findex NCVINQ
The function @code{ncvarinq} (or @code{NCVINQ} for FORTRAN) returns
information about a netCDF variable, given its ID.  The information
returned is the name, type, number of dimensions, a list of
dimension IDs describing the shape of the variable, and the number of
variable attributes that have been assigned to the variable.

In case of an error, @code{ncvarinq} returns -1; @code{NCVINQ} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarinq
@unnumberedsubsec ncvarinq:  C Interface
@example
int ncvarinq(int cdfid, int varid, char* name, nc_type* datatype,
             int* ndims, int dim[], int* natts);
@end example

@cindex variable name
@cindex variable type
@cindex variable dimensions
@cindex variable attributes
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@cindex maximum name length
@vindex MAX_NC_NAME
@item name
Returned variable name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
variable name is given by the predefined constant @code{MAX_NC_NAME}.
If the name parameter is given as @samp{(char *) 0}, no name will be
returned so no space needs to be allocated.

@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@item datatype
Returned variable type, one of the set of predefined netCDF data types.
The type of this parameter, @code{nc_type}, is defined in the netCDF
header file.  The valid netCDF data types are @code{NC_BYTE},
@code{NC_CHAR}, @code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and
@code{NC_DOUBLE}.

@item ndims
Returned number of dimensions the variable was defined as using.  For
example, @code{2} specifies a matrix, @code{1} specifies a vector, and @code{0} means the
variable is a scalar with no dimensions.

@cindex variable dimensions
@cindex maximum variable dimensions
@vindex MAX_VAR_DIMS
@item dim
Returned vector of @code{ndims} dimension IDs corresponding to the variable
dimensions.  The caller must allocate enough space for a vector of at least
@code{ndims} integers to be returned.  The maximum possible number of
dimensions for a variable is given by the predefined constant
@code{MAX_VAR_DIMS}.

@item natts
Returned number of variable attributes assigned to this variable.
@end table

@findex ncopen
@findex ncvarid
@findex ncvarinq
@vindex nc_type
@vindex NC_NOWRITE
@vindex MAX_VAR_DIMS
Here is an example using @code{ncvarinq} to find out about a variable
named @code{rh} in an existing netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
nc_type rh_type;                   /* variable type */
int rh_ndims;                      /* number of dims */
int  rh_dims[MAX_VAR_DIMS];        /* variable shape */
int rh_natts                       /* number of attributes */
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
/* we don't need name, since we already know it */
ncvarinq (cdfid, rh_id, (char *) 0, &rh_type, &rh_ndims, rh_dims,
          &rh_natts);
@end group
@end example

@findex NCVINQ
@unnumberedsubsec NCVINQ:  FORTRAN Interface
@example
      SUBROUTINE NCVINQ (INTEGER CDFID, INTEGER VARID,
     +                   CHARACTER*(*) VARNAM, INTEGER VARTYP,
     +                   INTEGER NVDIMS, INTEGER VDIMS(*),
     +                   INTEGER NVATTS, INTEGER RCODE)
@end example

@cindex variable name
@cindex variable type
@cindex variable dimensions
@cindex variable attributes
@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@cindex maximum name length
@vindex MAXNCNAM
@item VARNAM
Returned variable name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
variable name is given by the predefined constant @code{MAXNCNAM}.

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VARTYP
Returned variable type, one of the set of predefined netCDF data types.
The valid netCDF data types are @code{NCBYTE}, @code{NCCHAR},
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE}.

@item NVDIMS
Returned number of dimensions for the variable.  For example, @code{2}
specifies a matrix, @code{1} specifies a vector, and @code{0} means the
variable is a scalar with no dimensions.

@cindex maximum variable dimensions
@vindex MAXVDIMS
@item VDIMS
Returned vector of @code{NVDIMS} dimension IDs corresponding to the
variable dimensions.  The caller must allocate enough space for a vector
of at least @code{NVDIMS} integers to be returned.  The maximum possible
number of dimensions for a variable is given by the predefined constant
@code{MAXVDIMS}.

@item NVATTS
Returned number of variable attributes assigned to this variable.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVINQ
@vindex NCNOWRIT
@vindex MAXVDIMS
Here is an example using @code{NCVINQ} to find out about a variable
named @code{rh} in an existing netCDF file named @file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      CHARACTER*31 RHNAME         ! variable name
      INTEGER  RHTYPE             ! variable type
      INTEGER  RHN                ! number of dimensions
      INTEGER  RHDIMS(MAXVDIMS)   ! variable shape
      INTEGER  RHNATT             ! number of attributes
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)! get ID
      CALL NCVINQ (CDFID, RHID, RHNAME, RHTYPE, RHN, RHDIMS, RHNATT,
     +             RCODE)
@end group
@end example

@page
@node ncvarput1 and NCVPT1, ncvarput and NCVPT, ncvarinq and NCVINQ, Variables
@section Write a Single Data Value

@cindex putting variable data
@cindex writing data
@findex ncvarput1
@findex NCVPT1
@findex NCVP1C
The function @code{ncvarput1} (or @code{NCVPT1} or @code{NCVP1C} for
FORTRAN) puts a single data value into a variable of an open netCDF file
that is in data mode.  Inputs are the netCDF ID, the variable ID, a
multidimensional index that specifies which value to add or alter, and
the data value.

In case of an error, @code{ncvarput1} returns -1; @code{NCVPT1} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified indices were out of range for the dimensionality of the
specified variable.  For example, a negative index, or an index that is
larger than the corresponding dimension size will cause an error.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarput1
@unnumberedsubsec ncvarput1:  C Interface
@example
int ncvarput1(int cdfid, int varid, int mindex[], void *value);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item mindex
The multidimensional index of the the data value to be written.  the
indices are relative to 0, so for example, the first data value of a
two-dimensional variable would have index @code{(0,0)}.  The elements
of @code{mindex} must correspond to the variable's dimensions.  Hence, if
the variable is a record variable, the first index would correspond to
the record number.

@item value
Pointer to the data value to be written.  The pointer is declared to be
of type @code{void *} because it can point to data of any of the basic
netCDF types.  The data should be of the appropriate type for the netCDF
variable.  @strong{Warning: neither the compiler nor the netCDF software
can detect if the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarput1
@vindex NC_WRITE
Here is an example using @code{ncvarput1} to set the @code{(1,2,3)}
element of the variable named @code{rh} to @code{0.5} in an existing
netCDF file named @file{foo.cdf}.  For simplicity in this example, we
assume that we know that @code{rh} is dimensioned with @code{time},
@code{lat}, and @code{lon}, so we want to set the value of @code{rh} that
corresponds to the second @code{time} value, the third @code{lat} value,
and the fourth @code{lon} value:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
static int rh_index[] = @{1, 2, 3@}; /* where to put value */
static double rh_val = 0.5;        /* value to put */
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
ncvarput1(cdfid, rh_id, rh_index, (void *) &rh_val);
@end group
@end example

@findex NCVPT1
@unnumberedsubsec NCVPT1:  FORTRAN Interface
@example
      SUBROUTINE NCVPT1 (INTEGER CDFID, INTEGER VARID,
     +                   INTEGER MINDEX(*), @var{type} VALUE,
     +                   INTEGER RCODE)

      SUBROUTINE NCVP1C (INTEGER CDFID, INTEGER VARID,
     +                   INTEGER MINDEX(*), CHARACTER CHVAL,
     +                   INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCVPT1} and @code{NCVP1C}, for
putting a single value in a variable.  The first is for putting a
numeric value in a variable of numeric type, and the second is for
putting a character value in a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item MINDEX
The multidimensional index of the the data value to be written.  The
indices are relative to 1, so for example, the first data value of a
two-dimensional variable would have index @code{(1,1)}.  The elements
of @code{mindex} must correspond to the variable's dimensions.  Hence, if
the variable is a record variable, the last index would correspond to
the record number.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUE
For @code{NCVPT1}, the data value to be written.  The data may be of a
type corresponding to any of the netCDF types @code{NCSHORT},
@code{NCLONG}, @code{NCFLOAT}, or @code{NCDOUBLE}, but must be appropriate
for the type of the netCDF variable.  @strong{Warning: neither the
compiler nor the netCDF software can detect if the wrong type of data is
used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item CHVAL
For @code{NCVP1C}, the data value to be written.  The data should be of
a type character, corresponding to the netCDF types @code{NCCHAR} or
@code{NCBYTE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVPT1
Here is an example using @code{NCVPT1} to set the @code{(4,3,2)}
element of the variable named @code{rh} to @code{0.5} in an existing
netCDF file named @file{foo.cdf}.  For simplicity in this example, we
assume that we know that @code{rh} is dimensioned with @code{lon},
@code{lat}, and @code{time}, so we want to set the value of @code{rh} that
corresponds to the fourth @code{lon} value, the third @code{lat} value,
and the second @code{time} value:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  RHINDX(3)          ! where to put value
      DATA RHINDX /4, 3, 2/
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)  ! get ID
      CALL NCVPT1 (CDFID, RHID, RHINDX, 0.5, RCODE)
@end group
@end example

@page
@node ncvarput and NCVPT, ncvarget1 and NCVGT1, ncvarput1 and NCVPT1, Variables
@section Write a Hyperslab of Values

@cindex putting variable data
@cindex writing data
@cindex hyperslab access
@findex ncvarput
@findex NCVPT
@findex NCVPTC
The function @code{ncvarput} (or @code{NCVPT} or @code{NCVPTC} for
FORTRAN) writes a hyperslab of values into a netCDF variable of an open
netCDF file.  The hyperslab is specified by giving a corner and a vector
of edge lengths.  The values are specified as a vector whose elements
are ordered by assuming that the last dimension of the hyperslab varies
fastest for C, the first dimension varies fastest for FORTRAN.  The
netCDF file must be in data mode.

In case of an error, @code{ncvarput} returns -1; @code{NCVPT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified corner indices were out of range for the dimensionality of
the specified variable.  For example, a negative index, or an index that
is larger than the corresponding dimension size will cause an error.

@item
The specified edge lengths added to the specified corner would have
referenced data out of range for the dimensionality of the specified
variable.  For example, an edge length that is larger than the
corresponding dimension size minus the corner index will cause an error.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarput
@unnumberedsubsec ncvarput:  C Interface
@example
int ncvarput(int cdfid, int varid, int start[], int count[],
             void *values);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item start
A vector of integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
written.  The indices are relative to 0, so for example, the first data
value of a variable would have index @code{(0, 0, @dots{}, 0)}.  The
size of @code{start} must be the same as the number of dimensions of the
specified variable.  The elements of @code{start} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the first index would correspond to the starting record number
for writing the data values.

@item count
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
written.  To write a single value, for example, specify @code{count} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{count} is the number of
dimensions of the specified variable.  The elements of @code{count}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the first element of @code{count} corresponds to a
count of the number of records to write.

@item value
Pointer to a block of data values to be written.  The order in which the
data will be written into the specified hyperslab is with the last
dimension varying fastest.  The pointer is declared to be of the type
@code{void *} because it can point to data of any of the basic netCDF
types.  The data should be of the appropriate type for the netCDF
variable.  @strong{Warning: neither the compiler nor the netCDF software
can detect if the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarput
Here is an example using @code{ncvarput} to add or change all the values
of the variable named @code{rh} to @code{0.5} in an existing netCDF file
named @file{foo.cdf}.  For simplicity in this example, we assume that we
know that @code{rh} is dimensioned with @code{time}, @code{lat}, and
@code{lon}, and that there are three @code{time} values, five @code{lat}
values, and ten @code{lon} values.
@example 
@group
#include "netcdf.h"
   @dots{}
#define TIMES 3
#define LATS  5
#define LONS  10
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
static int start[] = @{0, 0, 0@};    /* start at first value */
static int count[] = @{TIMES, LATS, LONS@};
double rh_vals[TIMES*LATS*LONS];   /* array to hold values */
int i;
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
for (i = 0; i < TIMES*LATS*LONS; i++)
    rh_vals[i] = 0.5;
/* write hyperslab of values into netCDF variable */
ncvarput(cdfid, rh_id, start, count, (void *) rh_vals);
@end group
@end example

@page				@c because texinfo didn't do it right
@findex NCVPT
@unnumberedsubsec NCVPT:  FORTRAN Interface
@example
      SUBROUTINE NCVPT (INTEGER CDFID, INTEGER VARID,
     +                  INTEGER START(*), INTEGER COUNT(*),
     +                  @var{type} VALUES, INTEGER RCODE)

      SUBROUTINE NCVPTC(INTEGER CDFID, INTEGER VARID,
     +                  INTEGER START(*), INTEGER COUNTS(*),
     +                  CHARACTER*(*) STRING, INTEGER LENSTR,
     +                  INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCVPT} and @code{NCVPTC}, for
writing a hyperslab of values into a netCDF variable.  The first is for
writing numeric values into a variable of numeric type, and the second is
for writing character values into a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code

@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item START
A vector of integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
written.  The indices are relative to 1, so for example, the first data
value of a variable would have index @code{(1, 1, @dots{}, 1)}.  The
size of @code{START} must be the same as the number of dimensions of the
specified variable.  The elements of @code{START} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the last index would correspond to the starting record number
for writing the data values.

@item COUNT
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
written.  To write a single value, for example, specify @code{COUNT} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{COUNT} is the number of
dimensions of the specified variable.  The elements of @code{COUNT}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the last element of @code{COUNT} corresponds to a
count of the number of records to write.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUES
For @code{NCVPT}, the block of data values to be written.  The order in
which the data will be written into the specified hyperslab is with the
first dimension varying fastest (like the ordinary FORTRAN convention).
The data may be of a type corresponding to any of the netCDF types
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, or @code{NCDOUBLE}, but
must be appropriate for the type of the netCDF variable.
@strong{Warning: neither the compiler nor the netCDF software can detect
if the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item STRING
For @code{NCVPTC}, the characters to be written.  The order in which the
characters will be written into the specified hyperslab is with the
first dimension varying fastest (like the FORTRAN convention).  The data
may be of a type corresponding to the netCDF types @code{NCCHAR} or
@code{NCBYTE}.

@item LENSTR
For @code{NCVPTC}, the declared length of the @code{STRING} argument.
This should be at least as large as the product of the elements of the
@code{COUNT} vector.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVPT
Here is an example using @code{NCVPT} to add or change all the
values of the variable named @code{rh} to @code{0.5} in an existing
netCDF file named @file{foo.cdf}.  For simplicity in this example, we
assume that we know that @code{rh} is dimensioned with @code{lon},
@code{lat}, and @code{time}, and that there are ten @code{lon} values, five
@code{lat} values, and three @code{time} values.
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (NDIMS=3)         ! number of dimensions
      PARAMETER (TIMES=3, LATS=5, LONS=10) ! dimension sizes
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  START(NDIMS), COUNT(NDIMS) ! hyperslab
      DOUBLE RHVALS(LONS, LATS, TIMES)      
      DATA START /1, 1, 1/        ! start at first value
      DATA COUNT /LONS, LATS, TIMES/
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)   ! get ID
      DO 10 ILON = 1, LONS
         DO 10 ILAT = 1, LATS
            DO 10 ITIME = 1, TIMES
               RHVALS(ILON, ILAT, ITIME) = 0.5
   10 CONTINUE
      CALL NCVPT (CDFID, RHID, START, COUNT, RHVALS, RCODE)
@end group
@end example

@page
@node ncvarget1 and NCVGT1, ncvarget and NCVGT(C), ncvarput and NCVPT, Variables
@section Read a Single Data Value

@cindex getting variable data
@cindex reading data
@findex ncvarget1
@findex NCVGT1
@findex NCVG1C
The function @code{ncvarget1} (or @code{NCVGT1} or @code{NCVG1C} for
FORTRAN) gets a single data value from a variable of an open netCDF file
that is in data mode.  Inputs are the netCDF ID, the variable ID, a
multidimensional index that specifies which value to get, and
the address of a location into which the data value will be read.

In case of an error, @code{ncvarget1} returns -1; @code{NCVGT1} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified indices were out of range for the dimensionality of the
specified variable.  For example, a negative index or an index that is
larger than the corresponding dimension size will cause an error.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarget1
@unnumberedsubsec ncvarget1:  C Interface
@example
int ncvarget1(int cdfid, int varid, int mindex[], void *value);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item mindex
The multidimensional index of the the data value to be read.  The
indices are relative to 0, so for example, the first data value of a
two-dimensional variable would have index @code{(0,0)}.  The elements of
@code{mindex} must correspond to the variable's dimensions.  Hence, if
the variable is a record variable, the first index is the record number.

@item value
Pointer to the location into which the data value is read.  The pointer
is declared to be of the type @code{void *} because it can point to data
of any of the basic netCDF types.  The data should be of the appropriate
type for the netCDF variable.  @strong{Warning: neither the compiler nor
the netCDF software can detect if the wrong type for the data value is
used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarget1
Here is an example using @code{ncvarget1} to get the @code{(1,2,3)}
element of the variable named @code{rh} in an existing netCDF file named
@file{foo.cdf}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{time}, @code{lat}, and
@code{lon}, so we want to get the value of @code{rh} that corresponds to
the second @code{time} value, the third @code{lat} value, and the fourth
@code{lon} value:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
static int rh_index[] = @{1, 2, 3@}; /* where to get value */
double rh_val;                     /* where to put it */
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
ncvarget1(cdfid, rh_id, rh_index, (void *) &rh_val);
@end group
@end example

@findex NCVGT1
@unnumberedsubsec NCVGT1:  FORTRAN Interface
@example
      SUBROUTINE NCVGT1 (INTEGER CDFID, INTEGER VARID,
     +                   INTEGER MINDEX(*), @var{type} VALUE,
     +                   INTEGER RCODE)

      SUBROUTINE NCVG1C (INTEGER CDFID, INTEGER VARID,
     +                   INTEGER MINDEX(*), CHARACTER CHVAL,
     +                   INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCVGT1} and @code{NCVG1C}, for
reading a single value from a variable.  The first is for reading a
numeric value in a variable of numeric type, and the second is for
reading a character value in a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code

@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item MINDEX
The multidimensional index of the the data value to be read.  The
indices are relative to 1, so for example, the first data value of a
two-dimensional variable has index @code{(1,1)}.  The elements
of @code{mindex} correspond to the variable's dimensions.  Hence, if the
variable is a record variable, the last index is the record number.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUE
For @code{NCVGT1}, the location into which the data value will be read.
The data may be of a type corresponding to any of the netCDF types
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, or @code{NCDOUBLE}, but
must be appropriate for the type of the netCDF variable.
@strong{Warning: neither the compiler nor the netCDF software can detect
if the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item CHVAL
For @code{NCVG1C}, the location into which the data value will be read.
This should be of a type character, corresponding to the netCDF types
@code{NCCHAR} or @code{NCBYTE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@page				@c because texinfo didn't do it right
@findex NCOPN
@findex NCVID
@findex NCVGT1
Here is an example using @code{NCVGT1} to get the @code{(4,3,2)} element
of the variable named @code{rh} in an existing netCDF file named
@file{foo.cdf}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{lon}, @code{lat}, and
@code{time}, so we want to get the value of @code{rh} that corresponds to
the fourth @code{lon} value, the third @code{lat} value, and the second
@code{time} value:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  RHINDX(3)          ! where to get value
      DOUBLE PRECISION RHVAL      ! put it here
      DATA RHINDX /4, 3, 2/
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)! get ID
      CALL NCVGT1 (CDFID, RHID, RHINDX, RHVAL, RCODE)
@end group
@end example

@page
@node ncvarget and NCVGT(C), Character String I/O, ncvarget1 and NCVGT1, Variables
@section Read a Hyperslab of Values

@cindex putting variable data
@cindex reading data
@cindex hyperslab access
@findex ncvarget
@findex NCVGT
@findex NCVGTC
The function @code{ncvarget} (or @code{NCVGT} or @code{NCVGTC} for
FORTRAN) reads a hyperslab of values from a netCDF variable of an open
netCDF file.  The hyperslab is specified by giving a corner and a vector
of edge lengths.  The values are read into consecutive locations with
the last (or first for FORTRAN) dimension of the hyperslab varying
fastest.  The netCDF file must be in data mode.

In case of an error, @code{ncvarget} returns -1; @code{NCVGT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified corner indices were out of range for the dimensionality of
the specified variable.  For example, a negative index, or an index that
is larger than the corresponding dimension size will cause an error.

@item
The specified edge lengths added to the specified corner would have
referenced data out of range for the dimensionality of the specified
variable.  For example, an edge length that is larger than the
corresponding dimension size minus the corner index will cause an error.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarget
@unnumberedsubsec ncvarget:  C Interface
@example
int ncvarget(int cdfid, int varid, int start[], int count[],
             void *values);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item start
A vector of integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
read from.  The indices are relative to 0, so for example, the first data
value of a variable would have index @code{(0, 0, @dots{}, 0)}.  The
size of @code{start} must be the same as the number of dimensions of the
specified variable.  The elements of @code{start} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the first index would correspond to the starting record number
for reading the data values.

@item count
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
read.  To read a single value, for example, specify @code{count} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{count} is the number of
dimensions of the specified variable.  The elements of @code{count}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the first element of @code{count} corresponds to a
count of the number of records to read.

@item value
Pointer to the first of the locations into which the data values will be
read.  The order in which the data will be read from the specified
hyperslab is with the last dimension varying fastest.  The pointer is
declared to be of the type @code{void *} because it can point to data of
any of the basic netCDF types.  The data should be of the appropriate
type for the netCDF variable.  @strong{Warning: neither the compiler nor
the netCDF software can detect if the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarget
Here is an example using @code{ncvarget} to read all the values of the
variable named @code{rh} from an existing netCDF file named
@file{foo.cdf}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{time}, @code{lat}, and
@code{lon}, and that there are three @code{time} values, five @code{lat}
values, and ten @code{lon} values.
@example 
@group
#include "netcdf.h"
   @dots{}
#define TIMES 3
#define LATS  5
#define LONS  10
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
static int start[] = @{0, 0, 0@};    /* start at first value */
static int count[] = @{TIMES, LATS, LONS@};
double rh_vals[TIMES*LATS*LONS];   /* array to hold values */
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
/* read hyperslab of values from netCDF variable */
ncvarget(cdfid, rh_id, start, count, (void *) rh_vals);
@end group
@end example

@page				@c because texinfo didn't do it right
@findex NCVGT
@findex NCVGTC
@unnumberedsubsec NCVGT, NCVGTC:  FORTRAN Interface
@example
@group
      SUBROUTINE NCVGT (INTEGER CDFID, INTEGER VARID,
     +                  INTEGER START(*), INTEGER COUNT(*),
     +                  @var{type} VALUES, INTEGER RCODE)

      SUBROUTINE NCVGTC(INTEGER CDFID, INTEGER VARID,
     +                  INTEGER START(*), INTEGER COUNTS(*),
     +                  CHARACTER*(*) STRING, INTEGER LENSTR,
     +                  INTEGER RCODE)
@end group
@end example

There are two FORTRAN subroutines, @code{NCVGT} and @code{NCVGTC}, for
reading a hyperslab of values from a netCDF variable.  The first is for
reading numeric values from a variable of numeric type, and the second is
for reading character values from a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item START
A vector of integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
read.  The indices are relative to 1, so for example, the first data
value of a variable would have index @code{(1, 1, @dots{}, 1)}.  The
size of @code{START} must be the same as the number of dimensions of the
specified variable.  The elements of @code{START} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the last index would correspond to the starting record number
for reading the data values.

@item COUNT
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
read.  To read a single value, for example, specify @code{COUNT} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{COUNT} is the number of
dimensions of the specified variable.  The elements of @code{COUNT}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the last element of @code{COUNT} corresponds to a
count of the number of records to read.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUES
For @code{NCVGT}, the locations into which the data values will be read.
The order in which the data will be read from the specified hyperslab is
with the first dimension varying fastest (like the ordinary FORTRAN
convention).  The data may be of a type corresponding to any of the
netCDF types @code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, or
@code{NCDOUBLE}, but must be appropriate for the type of the netCDF
variable.  @strong{Warning: neither the compiler nor the netCDF software
can detect if the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item STRING
For @code{NCVGTC}, the character string into which the character data
will be read.  The order in which the characters will be read into the
specified hyperslab is with the first dimension varying fastest (like
the FORTRAN convention).
The data may be of a type corresponding to the netCDF types
@code{NCCHAR} or @code{NCBYTE}.

@item LENSTR
For @code{NCVGTC}, the declared length of the @code{STRING} argument.
This should be at least as large as the product of the elements of the
@code{COUNT} vector.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVGT
Here is an example using @code{NCVGT} to read all the values of the
variable named @code{rh} from an existing netCDF file named
@file{foo.cdf}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{lon}, @code{lat}, and
@code{time}, and that there are ten @code{lon} values, five @code{lat}
values, and three @code{time} values.
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (NDIMS=3)         ! number of dimensions
      PARAMETER (TIMES=3, LATS=5, LONS=10) ! dimension sizes
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  START(NDIMS), COUNT(NDIMS) ! hyperslab
      DOUBLE RHVALS(LONS, LATS, TIMES)      
      DATA START /1, 1, 1/        ! start at first value
      DATA COUNT /TIMES, LATS, LONS/
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)! get ID
      CALL NCVGT (CDFID, RHID, START, COUNT, RHVALS, RCODE)
@end group
@end example

@page
@node Character String I/O, Missing Values, ncvarget and NCVGT(C), Variables
@section Reading and Writing Character String Values

@cindex putting character string data
@cindex writing character string data
@cindex getting character string data
@cindex reading character string data
@cindex character string data
@cindex character strings
@cindex writing data
@cindex hyperslab access
@cindex fixed-length character strings
@cindex variable-length strings
@findex ncvarput
@findex NCVPT
@findex NCVPTC
@cindex reading data
@findex ncvarget
@findex NCVGT
@findex NCVGTC

Character strings are not a primitive netCDF data type, in part because
FORTRAN does not support the abstraction of variable-length character
strings.  As a result, a character string cannot be written or read as a
single object in the netCDF interface.  Instead, a character string must
be treated as an array of characters, and hyperslab access must be used
to read and write character strings as variable data in netCDF files.
Furthermore, variable-length strings are not supported by the netCDF
interface except by convention; for example, you may treat a null (zero)
byte as terminating a character string, but you must explicitly specify
the length of strings to be read from and written to netCDF variables.

@cindex character-string attributes
@cindex attribute length
Character strings as attribute values are easier to use, since the
strings are treated as a single unit for access; no hyperslab access is
necessary (or possible) for attributes.  However, the value of a
character-string attribute is still an array of characters with an
explicit length that must be specified when the attribute is defined.

@cindex character-position dimension
@cindex netCDF disk representation
@cindex netCDF file size
@cindex variable shape
When you define a variable that will have character-string values, use a
@var{character-position dimension} as the most quickly varying dimension
for the variable (the last dimension for the variable in C, the first in
FORTRAN).  The size of the character-position dimension will be the
maximum string length of any value to be stored in the character-string
variable.  Space for maximum-size strings will be allocated in the disk
representation of character-string variables whether you use the space
or not.  If two or more variables have the same maximum length, the same
character-position dimension may be used in defining the variable shapes.

@cindex hyperslab access
@cindex hyperslab corner
@cindex hyperslab edge lengths
To write a character-string value into a character-string variable, use
hyperslab access.  This requires that you specify both a corner and a
vector of edge lengths.  The character-position dimension at the corner
should be zero (one for FORTRAN).  If the length of the string to be
written is @code{n}, then the vector of edge lengths will specify
@code{n} in the character-position dimension, and one for all the other
dimensions, i.e., @code{(1, 1, @dots{}, 1, n)} (or @code{(n, 1, 1, @dots{},
1)} in FORTRAN).

@unnumberedsubsec C Interface

@cindex fixed-size strings
@cindex null byte
@cindex netCDF file size
@cindex variable-length strings
In C, fixed-size strings may be written to a netCDF file without the
terminating null byte, to save space.  Variable-length strings should be
written @emph{with} a terminating null byte so that the intended length
of the string can be determined when it is later read.

@findex ncvarput
@findex ncopen
@findex ncredef
@findex ncdimdef
@findex ncvardef
@findex ncendef
@vindex NC_CHAR
Here is an example that defines a record variable, @code{tx}, for
character strings and stores a character-string value into the third
record using @code{ncvarput}.  In this example, we assume the string
variable and data are to be added to an existing netCDF file named
@file{foo.cdf} that already has an unlimited record dimension @code{time}.

@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;           /* netCDF ID */
int  chid;            /* dimension ID for char positions */
int  timeid;          /* dimension ID for record dimension */
int  tx_id;           /* variable ID */
#define TDIMS 2       /* dimensionality of tx variable */
int tx_dims[TDIMS];   /* variable shape */
int tx_start[TDIMS];
int tx_count[TDIMS];
static char tx_val[] =
        "example string"; /* string to be put */
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);
ncredef(cdfid);       /* enter define mode */
   @dots{}
/* define character-position dimension for strings of max length 40 */
chid = ncdimdef(cdfid, "chid", 40);
   @dots{}
/* define a character-string variable */
tx_dims[0] = timeid;
tx_dims[1] = chid;    /* character-position dimension last */
tx_id = ncvardef (cdfid, "tx", NC_CHAR, TDIMS, tx_dims);
   @dots{}
ncendef(cdfid);       /* leave define mode */
   @dots{}
/* write tx_val into tx netCDF variable in record 3 */
tx_start[0] = 3;      /* record number to write */
tx_start[1] = 0;      /* start at beginning of variable */
tx_count[0] = 1;      /* only write one record */
tx_count[1] = strlen(tx_val) + 1;  /* number of chars to write */
ncvarput(cdfid, tx_id, tx_start, tx_count, (void *) tx_val);
@end group
@end example


@unnumberedsubsec FORTRAN Interface

@cindex fixed-size strings
@cindex null byte
@cindex netCDF file size
@cindex variable-length strings
In FORTRAN, fixed-size strings may be written to a netCDF file without a
terminating character, to save space.  Variable-length strings
should follow the C convention of writing strings with a terminating
null byte so that the intended length of the string can be determined
when it is later read by either C or FORTRAN programs.

@cindex character-string values
@cindex numeric values
@cindex string length, actual
@cindex string length, declared
@cindex character-position dimension
@findex NCVPTC
@findex NCVGTC
The FORTRAN interface for reading and writing strings requires the use
of different subroutines for accessing string values and numeric values,
because standard FORTRAN does not permit the same formal parameter to be
used for both character values and numeric values.  An additional
argument, specifying the declared length of the character string passed
as a value, is required for @code{NCVPTC} and @code{NCVGTC}.  The actual
length of the string is specified as the value of the hyperslab
edge-length vector corresponding to the character-position dimension.

@findex NCOPN
@findex NCREDF
@findex NCDDEF
@findex NCENDF
@findex NCVPTC
@findex NCVDEF
@vindex NCCHAR
Here is an example that defines a record variable, @code{tx}, for
character strings and stores a character-string value into the third
record using @code{NCVPTC}.  In this example, we assume the string
variable and data are to be added to an existing netCDF file named
@file{foo.cdf} that already has an unlimited record dimension
@code{time}.

@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (TDIMS=2)    ! number of TX dimensions
      PARAMETER (TXLEN = 15) ! length of example string
      INTEGER  CDFID, RCODE
      INTEGER  CHID          ! char position dimension id
      INTEGER  TIMEID        ! record dimension id
      INTEGER  TXID          ! variable ID
      INTEGER  TXDIMS(TDIMS) ! variable shape
      INTEGER  TSTART(TDIMS), TCOUNT(TDIMS) ! hyperslab
      CHARACTER*40 TXVAL     ! max length 40
      DATA TXVAL /'example string'/
         @dots{}
      TXVAL(TXLEN:TXLEN) = CHAR(0)   ! null terminate
         @dots{}
      CDFID = NCOPN('foo.cdf', NCWRITE, RCODE)
      CALL NCREDF(CDFID) ! enter define mode
         @dots{}
* define character-position dimension for strings of max length 40
      CHID = NCDDEF(CDFID, "chid", 40, RCODE)
         @dots{}
* define a character-string variable
      TXDIMS[1] = CHID   ! character-position dimension first
      TXDIMS[2] = TIMEID
      TXID = NCVDEF(CDFID, "tx", NCCHAR, TDIMS, TXDIMS, RCODE)
         @dots{}
      CALL NCENDF(CDFID) ! leave define mode
         @dots{}
* write txval into tx netCDF variable in record 3
      TSTART[1] = 0      ! start at beginning of variable
      TSTART[2] = 3      ! record number to write
      TCOUNT[1] = TXLEN  ! number of chars to write
      TCOUNT[2] = 1      ! only write one record
      CALL NCVPTC (CDFID, TXID, TSTART, TCOUNT, TXVAL, 40, RCODE)
@end group
@end example

@page
@node Missing Values, ncvarrename and NCVREN, Character String I/O, Variables
@section Missing Values

@cindex missing values
@cindex fill values
What happens when you try to read a value that was never written in an
open netCDF file?  You might expect that this should always be an error,
and that you should get an error message or an error status returned.
You @emph{do} get an error if you try to read data from a netCDF file
that is not open for reading, if the variable ID is invalid for the
specified netCDF file, or if the specified hyperslab is not properly
within the range defined by the dimension sizes of the specified
variable.  Otherwise, reading a value that was not written returns a
special @dfn{fill value} that is a particular value at one end of the
range of each netCDF type used to fill in any missing values when a
netCDF variable is first written.  It is also possible to use your own
fill value instead, if the default fill value is a useful value for the
variable, or to ignore fill values and use the entire range of each
netCDF type.

There are several reasons for using a fill value instead of an error
return for missing data.  First, the interface for hyperslab access
would necessarily be more complex and slower if information had to be
returned about whether each value read had been written.  Since data may
have been written in a different order from that in which it is later
read, it is possibile that only a few values in a block of retrieved
values were never written.  Second, it is usually preferable to delay
the detection of missing values until there is a need for the values,
since they may not be used in subsequent computations.  Finally, the use
of missing values is a common way to represent data points outside the
boundaries of irregular regions of data enclosed by a regular hyperslab,
making it possible to handle such data in a simpler way than would be
possible with a more compact representation that represented the
boundary explicitly.

The constant fill values for each type are defined in the include file
@file{netcdf.h} (or @file{netcdf.inc} for FORTRAN).  Fill values are
used for filling in missing data whenever a value is put beyond the end
of data that has already been written.  The fill values have no other
special meaning, so they can be used for valid values if there is no
need for fill values, or if alternate fill values are used.  To use an
alternate fill value for a variable, just initialize the variable with
the fill value before you begin writing data to it.  If you do this, you
should also define an associated variable attribute @code{missing_value}
with the appropriate type and value to capture your intent.

Currently the only difference between the netCDF byte and character
types is that the two types have different default fill values.  The
fill value for bytes is on the edge of the range, representing the
largest negative value for signed bytes.  The fill value for characters,
however, is the zero byte, a more useful value for detecting the end of
C character strings.


@page
@node ncvarrename and NCVREN,  , Missing Values, Variables
@section Rename a Variable

@cindex renaming variables
@cindex variable name
@findex ncvarrename
@findex NCVREN
The function @code{ncvarrename} (or @code{NCVREN} for FORTRAN) changes
the name of a netCDF variable in an open netCDF.  If the new name is
longer than the old name, the netCDF must be in define mode.  You cannot
rename a variable to have the name of any existing variable.

In case of an error, @code{ncvarrename} returns -1; @code{NCVREN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The new name is in use as the name of another variable.

@item
The variable ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarrename
@unnumberedsubsec ncvarrename:  C Interface
@example
int ncvarrename(int cdfid, int varid, char* name);
@end example

@cindex variable name

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item name
New name for the specified variable.
@end table

@findex ncopen
@findex ncvarid
@findex ncredef
@findex ncendef
@findex ncvarrename
Here is an example using @code{ncvarrename} to rename the variable
@code{rh} to @code{rel_hum} in an existing netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);
   @dots{}
ncredef(cdfid);  /* put in define mode to rename variable */
rh_id = ncvarid (cdfid, "rh");
ncvarrename (cdfid, rh_id, "rel_hum");
ncendef(cdfid);  /* leave define mode */
@end group
@end example

@page				@c because texinfo didn't do it right
@findex NCVREN
@unnumberedsubsec NCVREN:  FORTRAN Interface
@example
      SUBROUTINE NCVREN (INTEGER CDFID, INTEGER VARID,
     +                   CHARACTER*(*) NEWNAM, INTEGER RCODE)
@end example

@cindex variable name
@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item NEWNAM
New name for the specified variable.
@end table

@findex NCOPN
@findex NCVID
@findex NCVREN
@findex NCREDF
@findex NCENDF
Here is an example using @code{NCVREN} to rename the variable @code{rh}
to @code{rel_hum} in an existing netCDF file named @file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCWRITE, RCODE)
         @dots{}
      CALL NCREDF (CDFFID)  ! enter definition mode
      RHID = NCVID (CDFID, 'rh', RCODE)  ! get ID
      CALL NCVREN (CDFID, RHID, 'rel_hum', RCODE)
      CALL NCENDF (CDFFID)  ! leave definition mode
@end group
@end example

@node Attributes, Miscellaneous, Variables, Top
@chapter Attributes

@cindex attributes
@cindex define mode
@cindex attribute names
@cindex attribute type
@cindex attribute length
@cindex attribute values
@findex ncattname
@findex NCANAM
Attributes may be associated with each netCDF variable to specify such
properties as units, special values, maximum and minimum valid values,
scaling factors, and offsets.  Attributes for a netCDF file are
defined when it is first created, while the netCDF file is in define
mode.  Additional attributes may be added later by reentering define
mode.  A netCDF attribute has a netCDF variable to which it is assigned,
a name, a type, a length, and a sequence of one or more values.  An
attribute is designated by its variable ID and name, except in one case
(@code{ncattname} or @code{NCANAM} in FORTRAN), where attributes are
designated by variable ID and number because their names are unknown.

@cindex data mode
@cindex define mode
@cindex attribute type
@cindex attribute length
@cindex attribute values
@cindex attribute space
The attributes associated with a variable are typically defined right
after the variable is created, while still in define mode.  The data
type, length, and value of an attribute may be changed even when in data
mode, as long as the changed attribute requires no more space than the
attribute as originally defined.

@cindex global attributes
@vindex NC_GLOBAL
@cindex define mode
@cindex data mode
It is also possible to assign attributes not associated with any
variable to the netCDF as a whole, by using the @code{NC_GLOBAL} variable
pseudo-ID.  Global attributes may be used for purposes such as providing
a title or processing history for a netCDF data set.

@cindex attribute operations
Operations supported on attributes are
@itemize @bullet
@item
Create an attribute, given its variable ID, name, data type, length, and
value.

@item
Get attribute's data type and length from its variable ID and name.

@item
Get attribute's value from its variable ID and name.

@item
Copy attribute from one netCDF to another.

@item
Get name of attribute from its number.

@item
Rename an attribute.

@item
Delete an attribute.
@end itemize

@menu
* ncattput and NCAPT::      Create an Attribute
* ncattinq and NCAINQ::      Get Information about an Attribute
* ncattget and NCAGT(C)::      Get Attribute's Values
* ncattcopy and NCACPY::      Copy Attribute from One netCDF to Another
* ncattname and NCANAM::      Get Name of Attribute from Its Number
* ncattrename and NCAREN::      Rename an Attribute
* ncattdel and NCADEL::      Delete an Attribute
@end menu

@page
@node ncattput and NCAPT, ncattinq and NCAINQ,  , Attributes
@section Create an Attribute

@cindex creating attributes
@cindex defining attributes
@cindex variable attributes
@cindex global attributes
@findex ncattput
@findex NCAPT
@findex NCAPTC
The function @code{ncattput} (or @code{NCAPT} or @code{NCAPTC} for
FORTRAN) adds or changes a variable attribute or global attribute of an
open netCDF file.  If this attribute is new, or if the space required to
store the attribute is greater than before, the netCDF file must be in
define mode.

In case of an error, @code{ncattput} returns -1; @code{NCAPT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified netCDF type is invalid.

@item
The specified length is negative.

@item
The specified open netCDF file is in data mode and the specified
attribute would expand.

@item
The specified open netCDF file is in data mode and the specified
attribute does not already exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattput
@unnumberedsubsec ncattput:  C Interface
@example
int ncattput(int cdfid, int varid, char* name, nc_type datatype,
             int len, void* values);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex global attributes
@vindex NC_GLOBAL
@item varid
Variable ID of the variable to which the attribute will be assigned or
@code{NC_GLOBAL} for a global attribute.

@cindex attribute names
@item name
Attribute name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore
(@code{_}).  Case is significant.  Attribute name conventions are
assumed by some netCDF generic applications, e.g., @code{units} as the
name for a string attribute that gives the units for a netCDF variable.
@xref{Attribute Conventions}, for examples of attribute conventions.

@cindex attribute type
@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@item datatype
One of the set of predefined netCDF data types.  The type of this
parameter, @code{nc_type}, is defined in the netCDF header file.  The
valid netCDF data types are @code{NC_BYTE}, @code{NC_CHAR},
@code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE}.

@cindex data types
@vindex NC_CHAR
@item len
Number of values provided for the attribute.  If the attribute is of type
@code{NC_CHAR}, this is one more than the string length (since the
terminating null character is stored).

@cindex attribute values
@item values
Pointer to one or more data values.  The pointer is declared to be of
the type @code{void *} because it can point to data of any of the basic
netCDF types.  The data should be of the appropriate type for the netCDF
attribute.  @strong{Warning: neither the compiler nor the netCDF
software can detect if the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncattput
@findex ncredef
@vindex NC_GLOBAL
@vindex NC_CHAR
@vindex NC_DOUBLE
@findex ncendef
Here is an example using @code{ncattput} to add a variable attribute
named @code{valid_range} for a netCDF variable named @code{rh} and a
global attribute named @code{title} to an existing netCDF file named
@file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                        /* netCDF ID */
int  rh_id;                        /* variable ID */
static double rh_range[] = @{0.0, 100.0@};  /* attribute vals */
static char title[] = "example netCDF file";
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);
   @dots{}
ncredef(cdfid);                    /* enter define mode */
rh_id = ncvarid (cdfid, "rh");
   @dots{}
ncattput (cdfid, rh_id, "valid_range", NC_DOUBLE, 2, rh_range);
ncattput (cdfid, NC_GLOBAL, "title", NC_CHAR, strlen(title)+1,
          title);
   @dots{}
ncendef(cdfid);                    /* leave define mode */
@end group
@end example

@findex NCAPT
@findex NCAPTC
@unnumberedsubsec NCAPT, NCAPTC:  FORTRAN Interface
@example
      SUBROUTINE NCAPT (INTEGER CDFID, INTEGER VARID,
     +                  CHARACTER*(*) ATTNAM, INTEGER ATTYPE,
     +                  INTEGER ATTLEN, type VALUE,
     +                  INTEGER RCODE)

      SUBROUTINE NCAPTC (INTEGER CDFID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM, INTEGER ATTYPE,
     +                   INTEGER LENSTR, CHARACTER*(*) STRING,
     +                   INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCAPT} and @code{NCAPTC}, for
creating attributes.  The first is for attributes of numeric type, and
the second is for attributes of character-string type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@cindex attribute names
@item ATTNAM
Attribute name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore
(@code{_}).  Case is significant.  Attribute name conventions are
assumed by some netCDF generic applications, e.g., @code{units} as the
name for a string attribute that gives the units for a netCDF variable.
A table of conventional attribute names is presented in the earlier
chapter on the netCDF interface.

@cindex attribute type
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item ATTYPE
One of the set of predefined netCDF data types.  The valid netCDF data
types are @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT}, @code{NCLONG},
@code{NCFLOAT}, and @code{NCDOUBLE}.

@item ATTLEN
In @code{NCAPT}, the number of numeric values provided for the
attribute.

@item VALUE
In @code{NCAPT}, an array of @code{ATTLEN} data values.  The data should
be of the appropriate type for the netCDF attribute.  @strong{Warning:
neither the compiler nor the netCDF software can detect if the wrong
type of data is used.}

@item STRING
In @code{NCAPTC}, the character-string value of the attribute.

@item LENSTR
In @code{NCAPTC}, the actual string length of the @code{STRING} parameter.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCAPT
@findex NCREDF
@vindex NCDOUBLE
@findex NCAPTC
@vindex NCGLOBAL
@vindex NCCHAR
@findex NCENDF
Here is an example using @code{NCAPT} to add a variable attribute
named @code{valid_range} for a netCDF variable named @code{rh} and a
global attribute named @code{title} to an existing netCDF file named
@file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      DOUBLE RHRNGE(2)
      DATA RHRNGE /0.0D0, 100.0D0/
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCWRITE, RCODE)
         @dots{}
      CALL NCREDF (CDFID)     ! enter define mode
      RHID = NCVID (CDFID, 'rh', RCODE)! get ID
         @dots{}
      CALL NCAPT (CDFID, RHID, 'valid_range', NCDOUBLE, 2,
     +            RHRNGE, RCODE)
      CALL NCAPTC (CDFID, NCGLOBAL, 'title', NCCHAR, 19,
     +            'example netCDF file', RCODE)
         @dots{}
      CALL NCENDF (CDFID)     ! leave define mode
@end group
@end example

@page
@node ncattinq and NCAINQ, ncattget and NCAGT(C), ncattput and NCAPT, Attributes
@section Get Information about an Attribute

@cindex attribute inquire
@cindex attribute names
@cindex variable attributes
@cindex global attributes
@findex ncattinq
@findex NCAINQ
The function @code{ncattinq} (or @code{NCAINQ} for FORTRAN) returns
information about a netCDF attribute, given its variable ID and name.
The information returned is the type and length of the attribute.

In case of an error, @code{ncattinq} returns -1; @code{NCAINQ} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattinq
@unnumberedsubsec ncattinq:  C Interface
@example
int ncattinq(int cdfid, int varid, char* name,
             nc_type* datatype, int* len);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute.

@item name
Attribute name.

@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@vindex NC_CHAR
@item datatype
Returned attribute type, one of the set of predefined netCDF data types.
The type of this parameter, @code{nc_type}, is defined in the netCDF
header file.  The valid netCDF data types are @code{NC_BYTE},
@code{NC_CHAR}, @code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and
@code{NC_DOUBLE}.

@cindex data types
@item len
Returned number of values currently stored in the attribute.  If the
attribute is of type @code{NC_CHAR}, this is one more than the string
length (since the terminating null character is stored).
@end table

@findex ncopen
@findex ncvarid
@findex ncattinq
@vindex nc_type
@vindex NC_GLOBAL
Here is an example using @code{ncattinq} to find out the type and length
of a variable attribute named @code{valid_range} for a netCDF variable
named @code{rh} and a global attribute named @code{title} in an existing
netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                /* netCDF ID */
int  rh_id;                /* variable ID */
nc_type vr_type, t_type;   /* attribute types */
int  vr_len, t_len;        /* attribute lengths *'

   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
ncattinq (cdfid, rh_id, "valid_range", &vr_type, &vr_len);
ncattinq (cdfid, NC_GLOBAL, "title", &t_type, &t_len);
   @dots{}
@end group
@end example

@findex NCAINQ
@unnumberedsubsec NCAINQ:  FORTRAN Interface
@example
      SUBROUTINE NCAINQ (INTEGER CDFID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM, INTEGER ATTYPE,
     +                   INTEGER ATTLEN,INTEGER RCODE)
@end example

@cindex attribute names
@cindex attribute type
@cindex attribute length
@cindex global attributes
@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@cindex attribute variable ID
@vindex NCGLOBAL
@item VARID
Variable ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute.

@item ATTNAM
Attribute name.

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item ATTYPE
Returned attribute type, one of the set of predefined netCDF data types.  The
valid netCDF data types are @code{NCBYTE}, @code{NCCHAR},
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE}.

@item ATTLEN
Returned number of values currently stored in the attribute.  For a
string-valued attribute, this is the number of characters in the string.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCAINQ
@vindex NCGLOBAL
Here is an example using @code{NCAINQ} to add a variable attribute
named @code{valid_range} for a netCDF variable named @code{rh} and a
global attribute named @code{title} to an existing netCDF file named
@file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  VRTYPE, TTYPE      ! attribute types
      INTEGER  VRLEN, TLEN        ! attribute lengths
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)! get ID
         @dots{}
      CALL NCAINQ (CDFID, RHID, 'valid_range', VRTYPE, VRLEN,
     +             RCODE)
      CALL NCAINQ (CDFID, NCGLOBAL, 'title', TTYPE, TLEN,
     +             RCODE)
@end group
@end example

@page
@node ncattget and NCAGT(C), ncattcopy and NCACPY, ncattinq and NCAINQ, Attributes
@section Get Attribute's Values

@cindex getting attribute values
@cindex attribute values
@findex ncattget
@findex NCAGT
@findex NCAGTC
The function @code{ncattget} (or @code{NCAGT} or @code{NCAGTC} for
FORTRAN) gets the value(s) of a netCDF attribute, given its
variable ID and name.

In case of an error, @code{ncattget} returns -1; @code{NCAGT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattget
@unnumberedsubsec ncattget:  C Interface
@example
int ncattget(int cdfid, int varid, char* name, void* value);
@end example

@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex attribute variable ID
@vindex NC_GLOBAL
@item varid
Variable ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute.

@item name
Attribute name.

@cindex attribute values
@findex ncattinq
@item value
Returned attribute values.  All elements of the vector of attribute
values are returned, so you must allocate enough space to hold
them.  If you don't know how much space to reserve, call @code{ncattinq}
first to find out the length of the attribute.
@end table

@findex ncopen
@findex ncvarid
@findex ncattget
@vindex nc_type
@vindex NC_GLOBAL
@findex nctypelen
Here is an example using @code{ncattget} to determine the values of a
variable attribute named @code{valid_range} for a netCDF variable named
@code{rh} and a global attribute named @code{title} in an existing
netCDF file named @file{foo.cdf}.  In this example, it is assumed that
we don't know how many values will be returned, but that we do know the
types of the attributes.  Hence, to allocate enough space to store them,
we must first inquire about the length of the attributes.
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;                /* netCDF ID */
int  rh_id;                /* variable ID */
nc_type vr_type, t_type;   /* attribute types */
int  vr_len, t_len;        /* attribute lengths */
double *vr_val;            /* ptr to attribute values */
char *title;               /* ptr to attribute values */
extern char *malloc();     /* memory allocator */

   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
/* find out how much space is needed for attribute values */
ncattinq (cdfid, rh_id, "valid_range", &vr_type, &vr_len);
ncattinq (cdfid, NC_GLOBAL, "title", &t_type, &t_len);

/* allocate required space before retrieving values */
vr_val = (double *) malloc(vr_len * nctypelen(vr_type));
title = (char *) malloc(t_len * nctypelen(t_type));

/* get attribute values */
ncattget(cdfid, rh_id, "valid_range", (void *)vr_val);
ncattget(cdfid, NC_GLOBAL, "title", (void *)title);
   @dots{}
@end group
@end example

@findex NCAGT
@findex NCAGTC
@unnumberedsubsec NCAGT, NCAGTC:  FORTRAN Interface
@example
      SUBROUTINE NCAGT (INTEGER CDFID, INTEGER VARID,
     +                  CHARACTER*(*) ATTNAM, type VALUES,
     +                  INTEGER RCODE)

      SUBROUTINE NCAGTC (INTEGER CDFID, INTEGER VARID,
     +                  CHARACTER*(*) ATTNAM, CHARACTER*(*) STRING,
     +                  INTEGER LENSTR, INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCAGT} and @code{NCAGTC}, for
retrieving attribute values.  The first is for attributes of numeric
type, and the second is for attributes of character-string type.

@cindex attribute names
@cindex attribute type
@cindex attribute length
@cindex global attributes
@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute.

@item ATTNAM
Attribute name.

@cindex attribute values
@findex NCAINQ
@item VALUES
Returned attribute values.  All elements of the vector of attribute
values are returned, so the user must provide enough space to hold
them.  If you don't know how much space to reserve, call @code{NCAINQ}
first to find out the length of the attribute.  @strong{Warning:
neither the compiler nor the netCDF software can detect if the wrong
type of data is used.}

@item STRING
In @code{NCAGTC}, the character-string value of the attribute.

@item LENSTR
In @code{NCAGTC}, the actual string length of the @code{STRING}
parameter in the caller.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.

@end table

@findex NCOPN
@findex NCVID
@findex NCAGT
@findex NCAGTC
@findex NCAINQ
@vindex NCGLOBAL
Here is an example using @code{NCAGT} to determine the values of an
attribute named @code{valid_range} for a netCDF variable named @code{rh}
and a global attribute named @code{title} in an existing netCDF file
named @file{foo.cdf}.  In this example, it is assumed that we don't know
how many values will be returned, so we first inquire about the length
of the attributes to make sure we have enough space to store them:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (MVRLEN=3) ! max number of "valid_range" values
      PARAMETER (MTLEN=80) ! max length of "title" attribute
      INTEGER  CDFID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  VRTYPE, TTYPE      ! attribute types
      INTEGER  VRLEN, TLEN        ! attribute lengths
      DOUBLE PRECISION VRVAL(MVRLEN) ! vr attribute values
      CHARACTER*80 TITLE          ! title attribute values
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE) ! get ID
         @dots{}
* find out attribute lengths, to make sure we have enough space
      CALL NCAINQ (CDFID, RHID, 'valid_range', VRTYPE, VRLEN,
     +             RCODE)
      CALL NCAINQ (CDFID, NCGLOBAL, 'title', TTYPE, TLEN,
     +             RCODE)
* get attribute values, if not too big
      IF (VRLEN > MVRLEN) THEN
          WRITE (*,*) 'valid_range attribute too big!'
          CALL EXIT
      ELSE
          CALL NCAGT (CDFID, RHID, 'valid_range', VRVAL, RCODE)
      ENDIF
      IF (TLEN > MTLEN) THEN
          WRITE (*,*) 'title attribute too big!'
          CALL EXIT
      ELSE
          CALL NCAGTC (CDFID, NCGLOBAL, 'title', TITLE, MTLEN, RCODE)
      ENDIF
@end group
@end example

@page
@node ncattcopy and NCACPY, ncattname and NCANAM, ncattget and NCAGT(C), Attributes
@section Copy Attribute from One netCDF to Another

@cindex copying attributes
@findex ncattcopy
@findex NCACPY
The function @code{ncattcopy} (or @code{NCACPY} for FORTRAN) copies an
attribute from one open netCDF file to another.  It can also be used to
copy an attribute from one variable to another within the same netCDF.

In case of an error, @code{ncattcopy} returns -1; @code{NCACPY} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The input or output variable ID is invalid for the specified netCDF file.

@item
The specified attribute does not exist.

@item
The output netCDF is not in define mode and the attribute is new for the
output file is larger than the existing attribute.

@item
The input or output netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattcopy
@unnumberedsubsec ncattcopy:  C Interface
@example
int ncattcopy(int incdf, int invar, char* name, int outcdf, int outvar);
@end example

@table @code
@item incdf
The netCDF ID of an input netCDF file from which the attribute will be copied,
returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex variables
@vindex NC_GLOBAL
@item invar
ID of the variable in the input netCDF file from which the
attribute will be copied, or @code{NC_GLOBAL} for a global attribute.

@item name
Name of the attribute in the input netCDF file to be copied.

@item outcdf
The netCDF ID of the output netCDF file to which the attribute will be copied,
returned from a previous call to @code{ncopen} or @code{nccreate}.  It
is permissible for the input and output netCDF IDs to be the same.  The
output netCDF file should be in define mode if the attribute to be
copied does not already exist for the target variable, or if it would
cause an existing target attribute to grow.

@cindex variables
@vindex NC_GLOBAL
@item outvar
ID of the variable in the output netCDF file to which the attribute will
be copied, or @code{NC_GLOBAL} to copy to a global attribute.
@end table

@findex ncopen
@findex ncvarid
@findex ncredef
@findex ncendef
@findex ncattcopy
Here is an example using @code{ncattcopy} to copy the variable attribute
@code{units} from the variable @code{rh} in an existing netCDF file
named @file{foo.cdf} to the variable @code{avgrh} in another existing
netCDF file named @file{bar.cdf}, assuming that the variable
@code{avgrh} already exists, but does not yet have a @code{units}
attribute:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid1, cdfid2;       /* netCDF IDs */
int  rh_id, avgrh_id;      /* variable IDs */
   @dots{}
cdfid1 = ncopen("foo.cdf", NC_NOWRITE);
cdfid2 = ncopen("bar.cdf", NC_WRITE);
   @dots{}
rh_id = ncvarid (cdfid1, "rh");
avgrh_id = ncvarid (cdfid2, "avgrh");
   @dots{}
ncredef(cdfid2);           /* enter define mode */
/* copy variable attribute from "rh" to "avgrh" */
ncattcopy(cdfid1, rh_id, "units", cdfid2, avgrh_id);
   @dots{}
ncendef(cdfid2);           /* leave define mode */
@end group
@end example

@findex NCACPY
@unnumberedsubsec NCACPY:  FORTRAN Interface
@example
      SUBROUTINE NCACPY (INTEGER INCDF, INTEGER INVAR,
     +                   CHARACTER*(*) ATTNAM, INTEGER OUTCDF,
     +                   INTEGER OUTVAR, INTEGER RCODE)
@end example

@table @code
@item INCDF
The netCDF ID of an input netCDF file from which the attribute will be copied,
returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item INVAR
ID of the variable in the input netCDF file from which the
attribute will be copied, or @code{NCGLOBAL} for a global attribute.

@item ATTNAM
Name of the attribute in the input netCDF file to be copied.

@item OUTCDF
The netCDF ID of the output netCDF file to which the attribute will be copied,
returned from a previous call to @code{NCOPN} or @code{NCCRE}.  It
is permissible for the input and output netCDF IDs to be the same.  The
output netCDF file should be in define mode if the attribute to be
copied does not already exist for the target variable, or if it would
cause an existing target attribute to grow.

@cindex variable
@vindex NCGLOBAL
@item OUTVAR
ID of the variable in the output netCDF file to which the
attribute will be copied, or @code{NCGLOBAL} to copy to a global
attribute.
@end table

@findex NCOPN
@findex NCVID
@findex NCREDF
@findex NCENDF
@findex NCACPY
@vindex NCGLOBAL
Here is an example using @code{NCACPY} to copy the variable attribute
@code{units} from the variable @code{rh} in an existing netCDF file
named @file{foo.cdf} to the variable @code{avgrh} in another existing
netCDF file named @file{bar.cdf}, assuming that the variable
@code{avgrh} already exists, but does not yet have a @code{units}
attribute:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID1, CDFID2     ! netCDF IDs
      INTEGER  RHID, AVRHID       ! variable IDs
         @dots{}
      CDFID1 = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
      CDFID2 = NCOPN ('bar.cdf', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (CDFID1, 'rh', RCODE)
      AVRHID = NCVID (CDFID2, 'avgrh', RCODE)
         @dots{}
      CALL NCREDF (CDFID2)  ! enter define mode
* copy variable attribute from "rh" to "avgrh"
      CALL NCACPY (CDFID1, RHID, 'units', CDFID2, AVRHID, RCODE)
      CALL NCACPY (CDFID, NCGLOBAL, 'title', TITLE)
         @dots{}
      CALL NCENDF (CDFID2)  ! leave define mode
@end group
@end example

@page
@node ncattname and NCANAM, ncattrename and NCAREN, ncattcopy and NCACPY, Attributes
@section Get Name of Attribute from Its Number

@cindex getting attribute name
@cindex attribute names
@cindex attribute numbers
@cindex generic applications
@cindex attribute deletion
@cindex attribute ID
@findex ncattname
@findex NCANAM
The function @code{ncattname} (or @code{NCANAM} for FORTRAN) gets the
name of an attribute, given its variable ID and number as an attribute
of that variable.  This function is useful in generic applications that
need to get the names of all the attributes associated with a variable,
since attributes are accessed by name rather than number in all other
attribute functions.  The number of an attribute is more volatile than
the name, since it can change when other attributes of the same variable
are deleted.  This is why an attribute number is not called an attribute
ID.

In case of an error, @code{ncattname} returns -1; @code{NCANAM} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The specified variable ID is not valid.

@item
The specified attribute number is negative or more than the number of
attributes defined for the specified variable.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattname
@unnumberedsubsec ncattname:  C Interface
@example
int ncattname (int cdfid, int varid, int attnum, char* name);
@end example

@cindex attribute numbers
@cindex attribute names
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex attribute variable ID
@vindex NC_GLOBAL
@item varid
ID of the attribute's variable, or @code{NC_GLOBAL} for a global
attribute.

@findex ncvarinq
@item attnum
Number of the attribute.  The attributes for each variable are numbered
from 0 (the first attribute) to @code{nvatts-1}, where @code{nvatts} is
the number of attributes for the variable, as returned from a call to
@code{ncvarinq}.

@cindex maximum name length
@vindex MAX_NC_NAME
@item name
Returned attribute name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of an
attribute name is given by the predefined constant @code{MAX_NC_NAME}.
If the name parameter is given as @code{(char *) 0}, no name will be
returned so no space needs to be allocated.
@end table

@findex ncopen
@findex ncvarid
@findex ncattname
@vindex MAX_NC_NAME
Here is an example using @code{ncattname} to determine the name of the
first attribute of the variable @code{rh} in an existing netCDF file
named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;       /* netCDF ID */
int  rh_id;       /* variable ID */
char attname[MAX_NC_NAME];  /* maximum-size attribute name */
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
/* get name of first attribute (number 0) */
ncattname(cdfid, rh_id, 0, attname);
@end group
@end example

@findex NCANAM
@unnumberedsubsec NCANAM:  FORTRAN Interface
@example
      SUBROUTINE NCANAM (INTEGER CDFID, INTEGER VARID,
     +                   INTEGER ATTNUM, CHARACTER*(*) ATTNAM,
     +                   INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@cindex attribute variable ID
@vindex NCGLOBAL
@item VARID
ID of the attribute's variable, or @code{NCGLOBAL} for a global
attribute.

@findex NCVINQ
@item ATTNUM
Number of the attribute.  The attributes for each variable are numbered
from 1 (the first attribute) to @code{NVATTS}, where @code{NVATTS} is
the number of attributes for the variable, as returned from a call to
@code{NCVINQ}.

@cindex maximum name length
@vindex MAXNCNAM
@item ATTNAM
Returned attribute name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of an
attribute name is given by the predefined constant @code{MAXNCNAM}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCANAM
@vindex MAXNCNAM
Here is an example using @code{NCANAM} determine the name of the
first attribute of the variable @code{rh} in an existing netCDF file
named @file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID     ! netCDF ID
      INTEGER  RHID      ! variable ID
* 31 in the following should be MAXNCNAM
      CHARACTER*31 ATTNAM
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)
         @dots{}
* get name of first attribute (number 1)
      CALL NCANAM (CDFID, RHID, 1, ATTNAM, RCODE)
@end group
@end example

@page
@node ncattrename and NCAREN, ncattdel and NCADEL, ncattname and NCANAM, Attributes
@section Rename an Attribute


@cindex renaming attributes
@cindex attribute names
@findex ncattrename
@findex NCAREN
The function @code{ncattrename} (or @code{NCAREN} for FORTRAN) changes the
name of an attribute.  If the new name is longer than the original name,
the netCDF must be in define mode.  You cannot rename an attribute to
have the same name as another attribute of the same variable.

In case of an error, @code{ncattrename} returns -1; @code{NCAREN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The specified variable ID is not valid.
@item
The new attribute name is already in use for another attribute of the
specified variable.
@item
The specified netCDF file is in data mode and the new name is longer
than the old name.
@item
The specified attribute does not exist.
@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattrename
@unnumberedsubsec ncattrename:  C Interface
@example
int ncattrename (int cdfid, int varid, char* name, char* newname);
@end example

@cindex attribute names
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}
@item varid
variable ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute
@item name
The original attribute name.
@item newname
The new name to be assigned to the specified attribute.  If the new name
is longer than the old name, the netCDF file must be in define mode.
@end table

@findex ncopen
@findex ncvarid
@findex ncattrename
Here is an example using @code{ncattrename} to rename the variable
attribute @code{units} to @code{Units} for a variable @code{rh}
in an existing netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;       /* netCDF id */
int  rh_id;       /* variable id */
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
/* rename attribute */
ncattrename(cdfid, rh_id, "units", "Units");
@end group
@end example

@findex NCAREN
@unnumberedsubsec NCAREN:  FORTRAN Interface
@example
      SUBROUTINE NCAREN (INTEGER CDFID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM,
     +                   CHARACTER*(*) NEWNAM, INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}
@item VARID
variable ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute
@item ATTNAM
The original attribute name.
@item NEWNAM
The new name to be assigned to the specified attribute.  If the new name
is longer than the old name, the netCDF file must be in define mode.
@item RCODE
returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCAREN
Here is an example using @code{NCAREN} to rename the variable
attribute @code{units} to @code{Units} for a variable @code{rh}
in an existing netCDF file named @file{foo.cdf}:
@example 
@group
      INCLUDE "netcdf.inc"
         @dots{}
      INTEGER  CDFID     ! netCDF ID
      INTEGER  RHID      ! variable ID
         @dots{}
      CDFID = NCOPN ("foo.cdf", NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, "rh", RCODE)
         @dots{}
* rename attribute
      CALL NCAREN (CDFID, RHID, "units", "Units", RCODE);
@end group
@end example

@page
@node ncattdel and NCADEL,  , ncattrename and NCAREN, Attributes
@section Delete an Attribute

@cindex deleting attributes
@cindex removing attributes
@findex ncattdel
@findex NCADEL
The function @code{ncattdel} (or @code{NCADEL} for FORTRAN) deletes a
netCDF attribute from an open netCDF file.  The netCDF file must be in
define mode.

In case of an error, @code{ncattdel} returns -1; @code{NCADEL} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The specified variable ID is not valid.

@item
The specified netCDF file is in data mode.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattdel
@unnumberedsubsec ncattdel:  C Interface
@example
int ncattdel (int cdfid, int varid, char* name);
@end example

@cindex attribute names
@table @code
@item cdfid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex attribute variable ID
@vindex NC_GLOBAL
@item varid
Variable ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute.

@item name
The name of the attribute to be deleted.
@end table

@findex ncopen
@findex ncvarid
@findex ncattdel
@findex ncredef
@findex ncendef
Here is an example using @code{ncattdel} to delete the variable
attribute @code{Units} for a variable @code{rh} in an existing netCDF
file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;       /* netCDF ID */
int  rh_id;       /* variable ID */
   @dots{}
cdfid = ncopen("foo.cdf", NC_WRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
   @dots{}
/* delete attribute */
ncredef(cdfid);                  /* enter define mode */
ncattdel(cdfid, rh_id, "Units");
ncendef(cdfid);                  /* leave define mode */
@end group
@end example

@findex NCADEL
@unnumberedsubsec NCADEL:  FORTRAN Interface
@example
      SUBROUTINE NCADEL (INTEGER CDFID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM, INTEGER RCODE)
@end example

@table @code
@item CDFID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@cindex attribute variable ID
@vindex NCGLOBAL
@item VARID
Variable ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute.

@item ATTNAM
The original attribute name.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCADEL
@findex NCREDF
@findex NCENDF
Here is an example using @code{NCADEL} to delete the variable attribute
@code{Units} for a variable @code{rh} in an existing netCDF file named
@file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID     ! netCDF ID
      INTEGER  RHID      ! variable ID
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)
         @dots{}
* delete attribute
      CALL NCREDF (CDFID)  ! enter define mode
      CALL NCADEL (CDFID, RHID, 'Units', RCODE)
      CALL NCENDF (CDFID)  ! leave define mode
@end group
@end example

@node Miscellaneous, Utilities, Attributes, Top
@chapter Miscellaneous netCDF Operations

Other miscellaneous operations supported by this interface include

@itemize @bullet
@item
Get number of bytes for a given data type.
@end itemize

@menu
* nctypelen and NCTLEN::       Get Number of Bytes for a Data Type
@end menu

@page
@node nctypelen and NCTLEN,  ,  , Miscellaneous
@section  Get Number of Bytes for a Data Type

@cindex netCDF data types
@cindex data sizes
@cindex type lengths
@findex nctypelen
@findex NCTLEN
The function @code{nctypelen} (or @code{NCTLEN} for FORTRAN) returns
the number of bytes per netCDF data type.

In case of an error, @code{nctypelen} returns -1; @code{NCTLEN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include
@itemize @bullet
@item
The specified data type is not a valid netCDF data type.
@end itemize

@findex nctypelen
@unnumberedsubsec nctypelen:  C Interface
@example
int nctypelen (nc_type datatype);
@end example

@cindex attribute names
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@table @code
@item datatype
One of the set of predefined netCDF data types.  The type of this
parameter, @code{nc_type}, is defined in the netCDF header file.  The
valid netCDF data types are @code{NC_BYTE}, @code{NC_CHAR},
@code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE}.
@end table

@findex ncopen
@findex ncvarid
@findex ncvarinq
@findex nctypelen
@vindex nc_type
@vindex MAX_VAR_DIMS
Here is an example using @code{nctypelen} to determine how many bytes
are required to store a single value of the variable @code{rh} in an
existing netCDF file named @file{foo.cdf}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  cdfid;       /* netCDF ID */
int  rh_id;       /* variable ID */
nc_type rh_type;           /* variable type */
int rh_ndims;              /* number of dims */
int rh_dims[MAX_VAR_DIMS]; /* variable shape */
int rh_natts;              /* number of attributes */
int rhbytes;      /* number of bytes per value for "rh" */
   @dots{}
cdfid = ncopen("foo.cdf", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (cdfid, "rh");
/* get type.  we don't need name, since we already know it */
ncvarinq (cdfid, rh_id, (char *) 0, &rh_type, &rh_ndims, rh_dims,
          &rh_natts);
rhbytes = nctypelen (rh_type);
@end group
@end example

@findex NCTLEN
@unnumberedsubsec NCTLEN:  FORTRAN Interface
@example
      INTEGER FUNCTION NCTLEN (INTEGER TYPE ,INTEGER RCODE)
@end example

@table @code

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item TYPE
One of the set of predefined netCDF data types.  The valid netCDF data
types are @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT}, @code{NCLONG},
@code{NCFLOAT}, and @code{NCDOUBLE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVINQ
@findex NCTLEN
@vindex MAXVDIMS
Here is an example using @code{NCTLEN} to determine how many bytes are
required to store a single value of the variable @code{rh} in an existing
netCDF file named @file{foo.cdf}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  CDFID              ! netCDF ID
      INTEGER  RHID               ! variable ID
      CHARACTER*31 RHNAME         ! variable name
      INTEGER  RHTYPE             ! variable type
      INTEGER  RHN                ! number of dimensions
      INTEGER  RHDIMS(MAXVDIMS)   ! variable shape
      INTEGER  RHNATT             ! number of attributes
      INTEGER  RHBYTS             ! bytes per value
         @dots{}
      CDFID = NCOPN ('foo.cdf', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (CDFID, 'rh', RCODE)
* get type of "rh"
      CALL NCVINQ (CDFID, RHID, RHNAME, RHTYPE, RHN, RHDIMS, RHNATT,
     +             RCODE)
      RHBYTS = NCTLEN (RHTYPE)
@end group
@end example

@node Utilities, Getting the Software, Miscellaneous, Top
@chapter Higher-Level netCDF Operations

@cindex higher-level netCDF operations
@findex ncgen
@findex ncdump
One of the primary reasons for using the netCDF interface for both
scientific data and applications that deal with scientific data is to
take advantage of the higher-level netCDF operations and generic
applications for processing netCDF files.  Currently there are only a
few such higher-level operations available.  Below we describe
@code{ncgen} and @code{ncdump}, two tools for converting between binary
netCDF files and an ASCII representation of netCDF files.

@menu
* ncgen::         Check CDL syntax or generate netCDF file (or C or Fortran)
                  from netCDF file.
* CDL Syntax::    The syntax of CDL, a tiny language for representing
                  netCDF files or their structure in ASCII.
* CDL Data Types::The data types of CDL.
* CDL Constants:: The CDL notation for data constants.
* ncdump::        Generate CDL file (or a portion of a CDL file) from a netCDF
                  file.
@end menu

@page
@node ncgen, CDL Syntax,  , Utilities
@section ncgen

@findex ncgen
@cindex CDL
@cindex C, generation of
@cindex FORTRAN, generation of
@cindex CDF Description Language
@cindex generating code
@cindex generating netCDF files
@code{ncgen} is a tool that generates a netCDF file or the C or FORTRAN
programs required to create the netCDF file.  The input to @code{ncgen}
is a description of a netCDF file in a tiny language known as CDL
(netCDF description language).  If no options are specified in invoking
@code{ncgen}, the program merely checks the syntax of the CDL input,
producing error messages for any violations of CDL syntax.  Other
options can be used to create a netCDF file or to generate a program in
C or FORTRAN that calls the routines required to create the netCDF file.

UNIX syntax for invoking @code{ncgen}:
@example
ncgen [ -n]  [ -o @var{outputfile}]  [ -c]  [ -f]  [@var{inputfile}]
@end example
@noindent
where:
@table @code
@cindex netCDF file extension
@item -n
Create a netCDF file.    If the @code{-o} option is absent, a default file name
will be constructed from the netCDF name (specified after the
@code{netcdf} keyword in the input) by appending the @code{.cdf} extension.
If a file already exists with the specified name, it will be
overwritten.

@item -o outputfile
Name for the netCDF file created.  If this option is specified, it
implies the @code{-n} option.  (This option is necessary because netCDF
files are random access files created with @code{fseek()} calls, and
hence cannot be written to the standard output.)

@item -c
Generate C source code that will create a netCDF file matching the
netCDF specification.  The C source code is written to standard output.

@item -f
Generate FORTRAN source code that will create a netCDF file matching the
netCDF specification.  The FORTRAN source code is written to standard
output.
@end table

@node CDL Syntax, CDL Data Types, ncgen, Utilities
@unnumberedsubsec CDL Syntax

@cindex CDL syntax
@cindex CDL example
Below is an example of CDL, describing a netCDF file with several named
dimensions (@code{lat}, @code{lon}, @code{time}), variables
(@code{z}, @code{t}, @code{p}, @code{rh}, @code{lat}, @code{lon},
@code{time}), variable attributes (@code{units}, @code{valid_range},
@code{missing_value}), and some data.

@example
@group
netcdf foo @{    // example netCDF specification in CDL

dimensions:
lat = 9, lon = 5, time = unlimited ;

variables:
  long    lat(lat), lon(lon), time(time);
  float   z(time,lat,lon), t(time,lat,lon);
  double  p(time,lat,lon);
  long    rh(time,lat,lon);

  lat:units = "degrees North";
  lon:units = "degrees East";
  time:units = "seconds";
  z:units = "meters above sea level";
  z:valid range = 0., 5000.;
  p:missing value = -9999.;
  rh:missing value = -1;

data:
  lat   = 0, 10, 20, 30, 40, 50, 60, 70, 80, 90;
  lon   = -140, -118, -96, -84, -52;
@}
@end group
@end example

All CDL statements are terminated by a semicolon.  Spaces, tabs, and
newlines can be used freely for readability.  Comments may follow the
double slash characters @code{//} on any line.

A CDL description consists of three optional parts: dimensions,
variables, and data.  The variable part may contain variable
declarations and attribute assignments.

@cindex CDL dimensions
A dimension is used to define the shape of one or
more of the multidimensional variables described by the
CDL description.   A dimension has a name and a size.   At
most one dimension in a CDL description can have the unlimited size,
which means a variable using this dimension can grow to any
length (like a record number in a file).

@cindex CDL variables
@cindex coordinate variables
A variable represents a multidimensional array of values of the same
type.  A variable has a name, a data type, and a shape described by its
list of dimensions.  Each variable may also have associated attributes
(see below) as well as data values.  The name, data type, and shape of a
variable are specified by its declaration in the variable section of a
CDL description.  A variable may have the same name as a dimension; by
convention such a variable is one-dimensional and contains coordinates
of the dimension it names.  Dimensions need not have corresponding
variables.

@cindex CDL attributes
An attribute contains information about a variable or about the whole
netCDF data set.  Attributes are used to specify such properties as
units, special values, maximum and minimum valid values, scaling
factors, offsets, and parameters.  Attribute information is represented
by single values or arrays of values.  For example, @code{units} is an
attribute represented by a character array such as @code{degrees
Celsius}.  An attribute has an associated variable, a name, a data type,
a length, and a value.  In contrast to variables that are intended for
data, attributes are intended for metadata (data about data).

@cindex CDL attributes
@cindex variable attributes
@cindex global attributes
In CDL, an attribute is designated by a variable and attribute name,
separated by a colon (@code{:}).  It is possible to assign global
attributes not associated with any variable to the netCDF file as a
whole by using the colon (@code{:}) before the attribute name.  The data
type of an attribute in CDL is derived from the type of the value
assigned to it.  The length of an attribute is the number of data values
or the number of characters in the character string assigned to it.
Multiple values are assigned to noncharacter attributes by separating
the values with commas (@code{,}).  All values assigned to an attribute
must be of the same type.

@cindex data section
@cindex CDL variable initialization
@cindex CDL variables
The optional data section of a CDL description is where
netCDF variables may be initialized.  The syntax of an initialization
is simple:
@display
        @i{variable} = @i{value_1}, @i{value_2}, @dots{};
@end display
The comma-delimited list of constants may be separated by spaces, tabs,
and newlines.  For multidimensional arrays, the last dimension varies
fastest.  Thus, row-order rather than column order is used for matrices.
If fewer values are supplied than are needed to fill a variable, it is
extended with a type-dependent fill value.  The types of
constants need not match the type declared for a variable; coercions are
done to convert integers to floating point, for example.  All
meaningful type conversions are supported.

@node CDL Data Types, CDL Constants, CDL Syntax, Utilities
@unnumberedsubsec CDL Data Types

@cindex CDL data types
The CDL data types are:
@table @code
@item char
Character strings.

@item byte
Eight-bit data, including zero bytes.

@item short
16-bit signed integers.

@item long
32-bit signed integers.

@item int
(Synonymous with long).

@item float
IEEE single-precision floating point (32 bits).

@item real
(Synonymous with float).

@item double
IEEE double-precision floating point (64 bits).
@end table

@cindex CDL reserved words
Except for the added data-type @code{byte} and the lack of the type
qualifier @code{unsigned}, CDL supports the same primitive data types as C.
The names for the primitive data types are reserved words in
CDL, so the names of variables, dimensions, and attributes
must not be type names.  In declarations, type names may be
specified in either upper or lower case.

@cindex byte data type
@cindex char data type
@code{Byte}s differ from characters in that they are intended to hold
eight bits of data, and the zero byte has no special significance, as it
may for character data.  @code{ncgen} converts @code{byte} declarations
to @code{char} declarations in the output C code and to the nonstandard
@code{BYTE} declaration in output FORTRAN code.

@cindex short type
@code{Short}s can hold values between -32768 and 32767.  @code{ncgen} converts
@code{short} declarations to @code{short} declarations in the output
C code and to the nonstandard @code{INTEGER*2} declaration in output
FORTRAN code.

@cindex long type
@code{Long}s can hold values between -2147483648 and 2147483647.
@code{ncgen} converts @code{long} declarations to @code{long}
declarations in the output C code and to @code{INTEGER} declarations in
output FORTRAN code.  @code{int} and @code{integer} are accepted as
synonyms for @code{long} in CDL declarations.

@cindex float data type
@code{Float}s can hold values between about -3.4+38 and 3.4+38.
Their external representation is as 32-bit IEEE normalized
single-precision floating point numbers.  @code{ncgen} converts
@code{float} declarations to @code{float} declarations in the output C
code and to @code{REAL} declarations in output FORTRAN code.  @code{real}
is accepted as a synonym for @code{float} in CDL declarations.

@cindex double type
@code{Double}s can hold values between about -1.7+308 and 1.7+308.
Their external representation is as 64-bit IEEE standard
normalized double-precision, floating point numbers.  @code{ncgen}
converts @code{double} declarations to double declarations in the
output C code and to @code{DOUBLE PRECISION} declarations in output
FORTRAN code.

@node CDL Constants, ncdump, CDL Data Types, Utilities
@unnumberedsubsec CDL Notation for Data Constants

@cindex future changes planned
@cindex CDL constants
@findex ncdump
@findex ncgen
This section explains the current CDL notation for netCDF constants.
This remains one of the more volatile parts of the netCDF software.
Neither CDL nor the utility programs that use it (@code{ncdump} and
@code{ncgen}) are part of the netCDF procedural interface yet, and so
the information presented here is subject to change.

@cindex CDL attribute initialization
@cindex attribute type
@cindex attribute length
Attributes are initialized in the @code{variables} section of a CDL description
by providing a list of constants that determines the attribute's type
and length.  (In the C and FORTRAN procedural interfaces to the netCDF
library, the type and length of an attribute must be explicitly provided
when it is defined.)  Since neither C nor FORTRAN provide suitable
standard syntax to distinguish between constants of type @code{byte} and
@code{char}, @code{short} and @code{long}, or @code{float} and
@code{double} (except that FORTRAN provides the latter), CDL defines a
syntax for constant values that allows it to determine the netCDF type
of any constant.
@cindex double type
@cindex float type
@cindex long type
@cindex short type
@cindex CDL constants
The syntax for CDL constants is similar to C syntax, except that type
suffixes are appended to @code{short}s and @code{float}s to distinguish
them from @code{long}s and @code{double}s.

@cindex byte type
@cindex byte constant
A @code{byte} constant is represented by a single character or multiple
character escape sequence enclosed in single quotes.  For example,
@example
'a'     // ASCII a
'\0'    // a zero byte
'\n'    // ASCII newline character
'\33'   // ASCII escape character (33 octal)
'\x2b'  // ASCII plus (2b hex)
'\377'  // 377 octal = 255 decimal, a non-ASCII byte
@end example

@cindex character type
@cindex character constant
Character constants are enclosed in double quotes.  A character array
may be represented as a string enclosed in double quotes.  The usual
escape conventions for C strings are honored.  For example,
@example
"a"            // ASCII `a'
"Two\nlines\n" // a 10-character string with two embedded newlines
"a bell:\007"  // a string containing an ASCII bell
@end example

@cindex short type
@cindex short constant
The form of a @code{short} constant is an integer constant with an
@code{s} or @code{S} appended.  If a @code{short} constant begins with
@code{0}, it is interpreted as octal, except that if it begins with
@code{0x}, it is interpreted as a hexadecimal constant.  For example:
@example
2s      // a short 2
0123s   // octal
0x7ffs  // hexadecimal
@end example

@cindex long type
@cindex long constant
The form of a @code{long} constant is an ordinary integer constant,
although it is acceptable to append an optional @code{l} or @code{L}.
If a @code{long} constant begins with @code{0}, it is interpreted as
octal, except that if it begins with @code{0x}, it is interpreted as a
hexadecimal constant.  Examples of valid @code{long} constants include:
@example
-2
1234567890L
0123            // octal
0x7ff           // hexadecimal
@end example

@cindex float type
@cindex float constant
The @code{float} type is appropriate for representing
data with about seven significant digits of precision.
The form of a @code{float} constant is the same as a C floating-point constant
with an @code{f} or @code{F} appended.  A decimal point is required in a CDL
@code{float} to distinguish it from an integer.  For example,
the following are all acceptable @code{float} constants:
@example
-2.0f
3.14159265358979f       // will be truncated to less precision
1.f
.1f
@end example

@cindex double type
@cindex double constant
The @code{double} type is appropriate for representing floating-point
data with about 16 significant digits of precision.  The form of a
@code{double} constant is the same as a C floating point constant.  An
optional @code{d} or @code{D} may be appended.  A decimal point is
required in a CDL @code{double} to distinguish it from an
@code{integer}.  For example, the following are all acceptable double
constants:
@example
-2.0
3.141592653589793
1.0e-20
1.d
@end example

@page
@node ncdump,  , CDL Constants, Utilities
@section ncdump

@findex ncdump
@findex ncgen
@code{ncdump} is a tool that generates an ASCII representation of a
netCDF file, either with or without an ASCII representation of the
variable data in the file.  The ASCII representation used is the CDL
notation that @code{ncgen} accepts as input.  Thus @code{ncdump} and
@code{ncgen} can be used as inverses to transform data representation
between binary and ASCII representations.

UNIX syntax for invoking @code{ncdump}:
@example
ncdump [ -h]  [ -c]  [ -n @var{name}]  [@var{inputfile}]
@end example
@noindent
where:
@table @code
@item -h
Produce only the ``header'' information in the output file; that is,
the declarations of dimensions and variables but no data values for
the variables.

@item -c
Produce the ``header'' information in the output file
and the data values for coordinate variables (variables that are
also dimensions).

@item -n name
Specify a different name for the CDL description than the default.  CDL
requires a name for a CDL description that is used by @code{cdfgen} to
generate the file name for an output netCDF file.  By default this name
is constructed from the last component of the pathname of the input file
by stripping off any extension it has (conventionally, @code{.cdf} is used
as an extension for netCDF files).  Use this option to specify a
different name.
@end table

@node Getting the Software, C Interface, Utilities, Top
@chapter How to Obtain netCDF Software

@cindex obtaining netCDF software
@cindex FTP access
@cindex computing environments
@cindex ports of netCDF

The current version of netCDF software is available using anonymous FTP.

The netCDF C interface has been compiled and tested successfully on a
Sun 3 and SPARCstation under SunOS, a DEC VAX under VMS, a DEC VAX and
DECstation 3100 under Ultrix, an Apple Macintosh II under MacOS, a
Compaq 80386 under 386-ix, a NeXT under MACH, a Stellar under Stellix ,
and a Cray XMP under UNICOS.  Since there is no standard for FORTRAN to
C interfaces, the set of FORTRAN jackets that provide the FORTRAN
interface on top of the C library varies for each machine architecture
and set of compilers.  Consequently, the FORTRAN interface has so far
only been tested successfully on a Sun 3 and SPARCstation under SunOS, a
DEC VAX under VMS, a DEC VAX under Ultrix, and a DECstation 3100 under
Ultrix.

Included in the software distribution are: the C source for the netCDF
data access library, C source for the FORTRAN jacket library for UNIX
and VMS FORTRAN compilers, source for the netCDF utilities ncdump and
ncgen, a directory of test programs to verify the correct implementation
of the netCDF library in new environments, and XDR source code for
environments that do not yet support XDR.  Instructions for porting the
netCDF software to a new environment are also included.

For UNIX systems, a compressed tar file can be accessed (in binary mode)
from the file @code{netcdf.tar.Z} in the anonymous FTP directory of
@code{unidata.ucar.edu}.  VMS sites can get a backup saveset of the same
software from the anonymous FTP directory of @code{laurel.ucar.edu}.
The software distribution includes a PostScript file of the netCDF
User's Guide.

@cindex reporting bugs
@cindex mailing list
@cindex netcdfgroup
A mailing list, @code{netcdfgroup@@unidata.ucar.edu}, is available for
discussion of the netCDF interface and announcements about netCDF bugs,
fixes, and enhancements.  To subscribe, send a request to
@code{netcdfgroup-adm@@unidata.ucar.edu}.

@node C Interface, Fortran Interface, Getting the Software, Top
@chapter Summary of C Interface

@example
int nccreate(char* path,int cmode);
int ncopen(char* path,int mode);
int ncredef(int cdfid);
int ncendef(int cdfid);
int ncclose(int cdfid);
int ncinquire(int cdfid,int* ndims,int* nvars,int* natts,int* recdim);
int ncsync(int cdfid);
int ncabort(int cdfid);
int ncdimdef(int cdfid,char* name,int length);
int ncdimid(int cdfid,char* name);
int ncdiminq(int cdfid,int dimid,char* name,int* length);
int ncdimrename(int cdfid,int dimid,char* name);
int ncvardef(int cdfid,char* name,nc_type datatype,int ndims,int dim[]);
int ncvarid(int cdfid,char* name);
int ncvarinq(int cdfid,int varid,char* name,nc_type* datatype,int* ndims,
               int dim[],int* natts);
int ncvarput1(int cdfid,int varid,int coords[],void* value);
int ncvarget1(int cdfid,int varid,int coords[],void* value);
int ncvarput(int cdfid,int varid,int start[],int count[],void* value);
int ncvarget(int cdfid,int varid,int start[],int count[],void* value);
int ncvarrename(int cdfid,int varid,char* name);
int ncattput(int cdfid,int varid,char* name,nc_type datatype,int len,
              void* value);
int ncattinq(int cdfid,int varid,char* name,nc_type* datatype,int* len);
int ncattget(int cdfid,int varid,char* name,void* value);
int ncattcopy(int incdf,int invar,char* name,int outcdf,int outvar);
int ncattname(int cdfid,int varid,int attnum,char* name);
int ncattrename(int cdfid,int varid,char* name,char* newname);
int ncattdel(int cdfid,int varid,char* name);
int nctypelen(nc_type datatype);
@end example

@node Fortran Interface, Name Index, C Interface, Top
@chapter Summary of FORTRAN Interface

Input parameters are in upper case, output parameters are in lower
case.  The FORTRAN types of all the parameters are listed below the
subroutine and function declarations.

@example
INTEGER FUNCTION NCCRE(PATHNAME,CLOBMODE, rcode)
INTEGER FUNCTION NCOPN(PATHNAME,RWMODE, rcode)
SUBROUTINE NCREDF(CDFID, rcode)
SUBROUTINE NCENDF(CDFID, rcode)
SUBROUTINE NCCLOS(CDFID, rcode)
SUBROUTINE NCINQ(CDFID, ndims,nvars,natts,recdim,rcode)
SUBROUTINE NCSNC(CDFID, rcode)
SUBROUTINE NCABOR(CDFID, rcode)
INTEGER FUNCTION NCDDEF(CDFID,DIMNAME,SIZE, rcode)
INTEGER FUNCTION NCDID(CDFID,DIMNAME, rcode)
SUBROUTINE NCDINQ(CDFID,DIMID, dimname,size,rcode)
SUBROUTINE NCDREN(CDFID,DIMID,DIMNAME, rcode)
INTEGER FUNCTION NCVDEF(CDFID,VARNAME,DATATYPE,NVDIMS,VDIMS, rcode)
INTEGER FUNCTION NCVID(CDFID,VARNAME, rcode)
SUBROUTINE NCVINQ(CDFID,VARID, varname,datatype,nvdims,vdims,nvatts,rcode)
SUBROUTINE NCVPT1(CDFID,VARID,INDICES,VALUE, rcode)
SUBROUTINE NCVP1C(CDFID,VARID,INDICES, CHVAL, rcode)
SUBROUTINE NCVGT1(CDFID,VARID,INDICES, value, rcode)
SUBROUTINE NCVG1C(CDFID,VARID,INDICES, chval, rcode)
SUBROUTINE NCVPT(CDFID,VARID,START,COUNTS,VALUE, rcode)
SUBROUTINE NCVPTC(CDFID,VARID,START,COUNTS,STRING,LENSTR, rcode)
SUBROUTINE NCVGT(CDFID,VARID,START,COUNTS, value,rcode)
SUBROUTINE NCVGTC(CDFID,VARID,START,COUNTS, string,LENSTR,rcode)
SUBROUTINE NCVREN(CDFID,VARID,VARNAME, rcode)
SUBROUTINE NCAPT(CDFID,VARID,ATTNAME,DATATYPE,ATTLEN,VALUE, rcode)
SUBROUTINE NCAPTC(CDFID,VARID,ATTNAME,DATATYPE,LENSTR,STRING, rcode)
SUBROUTINE NCAINQ(CDFID,VARID,ATTNAME, datatype,attlen,rcode)
SUBROUTINE NCAGT(CDFID,VARID,ATTNAME, value,rcode)
SUBROUTINE NCAGTC(CDFID,VARID,ATTNAME, string,LENSTR,rcode)
SUBROUTINE NCACPY(INCDFID,INVARID,ATTNAME,OUTCDFID,OUTVARID, rcode)
SUBROUTINE NCANAM(CDFID,VARID,ATTNUM, attname,rcode)
SUBROUTINE NCAREN(CDFID,VARID,ATTNAME,NEWNAME, rcode)
SUBROUTINE NCADEL(CDFID,VARID,ATTNAME, rcode)
INTEGER FUNCTION NCTLEN(DATATYPE, rcode)
SUBROUTINE NCPOPT(NCOPTS)
SUBROUTINE NCGOPT(ncopts)

CHARACTER*(*) PATHNAME  ! absolute or relative name of netCDF file
INTEGER CLOBMODE        ! either NCCLOB or NCNOCLOB
INTEGER RWMODE          ! either NCWRITE or NCNOWRIT
INTEGER RCODE           ! returned error code, 0 if no errors
INTEGER CDFID           ! netCDF ID, returned by NCCRE or NCOPN
INTEGER NDIMS           ! number of dimensions in netCDF
INTEGER NVARS           ! number of variables in netCDF
INTEGER NATTS           ! number of global attributes in netCDF
INTEGER RECDIM          ! dimension ID of unlimited dimension
CHARACTER*(*) DIMNAME   ! name for dimension
INTEGER SIZE            ! size of dimension
INTEGER DIMID           ! dimension ID from NCDDEF or NCDID
CHARACTER*(*) VARNAME   ! name for variable
INTEGER DATATYPE        ! data type code, one of NCBYTE, ..., NCDOUBLE
INTEGER NVDIMS          ! number of dimensions in a variable
INTEGER VDIMS(NDIMS)    ! dimension IDs for a variable, giving its shape
INTEGER VARID           ! variable ID from NCVDEF or NCVID, or NCGLOBAL
INTEGER NVATTS          ! number of attributes assigned to a variable
INTEGER INDICES(NDIMS)  ! coordinates of a single element of a variable
CHARACTER CHVAL         ! character value of variable or attribute
CHARACTER*(*) STRING    ! character array value of variable or attribute
INTEGER LENSTR          ! length of character array value
DOUBLE VALUE            ! double precision value of variable or attribute
REAL VALUE              ! real value of variable or attribute
INTEGER VALUE           ! integer value of variable or attribute
INTEGER START(NVDIMS)   ! corner of hyperslab of values of a variable
INTEGER COUNTS(NVDIMS)  ! edge lengths of hyperslab of values
CHARACTER*(*) ATTNAME   ! attribute name
INTEGER ATTLEN          ! number of elements in an attribute vector
INTEGER INCDFID         ! input netCDF ID
INTEGER INVARID         ! input variable ID
INTEGER OUTCDFID        ! output netCDF ID
INTEGER OUTVARID        ! output variable ID
INTEGER ATTNUM          ! attribute number
CHARACTER*(*) NEWNAME   ! new attribute name
INTEGER VARIDS(*)       ! IDs of variables in netCDF link subset
INTEGER DIMINS(*)       ! lower limit of indices in hyperslab of link
INTEGER DIMAXS(*)       ! upper limit of indices in hyperslab of link
INTEGER LNCDFID         ! netCDF ID of link
@end example

@node Name Index, General Index, Fortran Interface, Top
@unnumbered Function and Variable Index

@printindex fn

@node General Index, , Name Index, Top
@unnumbered General Index

@printindex cp


@c Print the tables of contents
@contents

@c That's all
@bye
